【问题标题】:Enum styled factory as inner Enum in Java枚举风格的工厂作为 Java 中的内部枚举
【发布时间】:2017-08-16 03:41:20
【问题描述】:

我尝试将 Enum 风格的工厂模式实现为内部 Enum, 但它没有用。 有没有不将内部枚举分离到新文件中的解决方案? 换句话说,内部 Enum 风格的工厂模式是否可能?

代码如下。

public class SampleParent {

    private class InnerChild { }
    private class InnerChildA extends InnerChild { }
    private class InnerChildB extends InnerChild { }
    private class InnerChildC extends InnerChild { }

    enum InnerChildEnum {
        CHILD_A {
            @Override
                public InnerChild getInstance() {
                    return new InnerChildA();  // compile error
                }
        },
        CHILD_B {
            @Override
                public InnerChild getInstance() {
                    return new SampleParent.InnerChildB();  // compile error
                }
        },
        CHILD_C {
            @Override
                public InnerChild getInstance() {
                    return SampleParent.new InnerChildC();  // compile error
                }
        },
        ;

        public abstract InnerChild getInstance();
    }

    private static class InnerChildFactoryEnumStyled {
        public static InnerChild getInnerChild(InnerChildEnum child) {
            return child.getInstance();
        }
    }


    public static void main(String[] args) {

        // I want to write this way
        InnerChild child = InnerChildFactoryEnumStyled.getInnerChild(InnerChildEnum.CHILD_A);
    }
}

编译错误信息如下

$ javac SampleParent.java 
SampleParent.java:12: error: non-static variable this cannot be referenced from a static context
                return new InnerChildA();
                       ^
SampleParent.java:18: error: non-static variable this cannot be referenced from a static context
                return new SampleParent.InnerChildB();
                       ^
SampleParent.java:24: error: cannot find symbol
                return SampleParent.new InnerChildC();
                       ^
  symbol: variable SampleParent
3 errors

【问题讨论】:

  • 您可以简单地将 InnerChildXX 类设为静态。根据您的示例,这不是问题。
  • 谢谢,正如我在下面提到的,不幸的是,实际的内部类是 AsyncTask 的子类,不能是静态的。

标签: java enums factory


【解决方案1】:

您的内部类不是静态的,因此它们必须引用封闭类SampleParent 的实例。将您的类声明更改为

private static class InnerChild { }
private static class InnerChildA extends InnerChild { }
private static class InnerChildB extends InnerChild { }
private static class InnerChildC extends InnerChild { }

你可以 e. G。 return new InnerChildA(); 在您的枚举中。

【讨论】:

  • 我看到你在我之前发布了你的答案,所以我删除了我的帖子。
  • 感谢您的解决方案。改变静态是有意义的。但不幸的是,实际的内部类是 AsyncTask 的子类,并且子类具有非静态成员。你的回答很有帮助。
【解决方案2】:

要实例化非静态内部类(InnerChildAInnerChildB 等...),您需要使用封闭类型(SampleParent)的实例来限定实例化。 你必须这样做:new ExternalClass().new InternalClass()

在您的情况下,您可以在 InnerChildEnum 枚举中声明和实例化一个静态 SampleParent 实例,并在枚举值声明的每个实现的 getInstance() 方法中重用它。

private class InnerChild {
}

private class InnerChildA extends InnerChild {
}

private class InnerChildB extends InnerChild {
}

private class InnerChildC extends InnerChild {
}

enum InnerChildEnum {

    CHILD_A {
        @Override
        public InnerChild getInstance() {
            return sampleParent.new InnerChildA();
        }
    },
    CHILD_B {
        @Override
        public InnerChild getInstance() {

            return sampleParent.new InnerChildB(); // compile error
        }
    },
    CHILD_C {
        @Override
        public InnerChild getInstance() {
            return sampleParent.new InnerChildC();
        }
    };

    private static SampleParent sampleParent = new SampleParent();

    public abstract InnerChild getInstance();
}

【讨论】:

  • 感谢您的帖子,我会尝试并报告。
  • 第一个问题解决了。不幸的是,我遇到了另一个问题。 Enum 中创建的实例和原始实例是不同的对象。因此,如果 SampleParent 有非实例成员,则创建的实例不能引用原始实例的成员。但这是第二个问题。我试着解决。
  • 我想你会说“如果 SampleParent 有实例成员......”。要解决您的问题,您应该在这两个类之间共享此实例,甚至可以确保您拥有不超过一个 SampleParent 实例。简单的方法(共享实例):将private static SampleParent sampleParent = new SampleParent(); 替换为public static SampleParent sampleParent = new SampleParent(); 现在您可以在任何地方引用同一个对象,因为它是公开的
  • 关于运行时不超过单个实例的方法,您可以使用经典的单例模式或依赖注入。
【解决方案3】:

改进代码在这里,以防万一。

public class SampleParent {

    private String foo = "foo";

    private abstract class InnerChild {
        public abstract void doSomething();
    }
    private class InnerChildA extends InnerChild {
        public void doSomething() {
            System.out.println(foo);  // refer sampleParent.foo, not original's foo
        }
    }
    private class InnerChildB extends InnerChild {
        public void doSomething() {
            System.out.println(foo);  // refer sampleParent.foo, not original's foo
        }
    }
    private class InnerChildC extends InnerChild {
        public void doSomething() {
            System.out.println(outer().foo);  // refer sampleParent.foo, not original's foo
        }
    }

    enum InnerChildEnum {
        CHILD_A {
            @Override
            public InnerChild getInstance() {
                return sampleParent.new InnerChildA();
            }
        },
        CHILD_B {
            @Override
            public InnerChild getInstance() {
                return sampleParent.new InnerChildB();
            }
        },
        CHILD_C {
            @Override
            public InnerChild getInstance() {
                return sampleParent.new InnerChildC();
            }
        },
        ;

        private static SampleParent sampleParent = new SampleParent();
        public abstract InnerChild getInstance();
    }

    private static class InnerChildFactoryEnumStyled {
        public static InnerChild getInnerChild(InnerChildEnum child) {
            return child.getInstance();
        }
    }


    public static void main(String[] args) {
        System.out.println("Hello World.");

        // I want to write this way
        InnerChild childA = InnerChildFactoryEnumStyled.getInnerChild(InnerChildEnum.CHILD_A);
        childA.doSomething();

        InnerChild childB = InnerChildFactoryEnumStyled.getInnerChild(InnerChildEnum.CHILD_B);
        childB.doSomething();

        InnerChild childC = InnerChildFactoryEnumStyled.getInnerChild(InnerChildEnum.CHILD_C);
        childC.doSomething();
    }

    public SampleParent outer() {
        return SampleParent.this;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-19
    • 2020-10-19
    • 1970-01-01
    • 2010-12-10
    相关资源
    最近更新 更多