最近我一直在尝试做一个相对论的能量计算器。我用List<ComponentType>表示任何在ComponentType.ELECTRONComponentType.PROTONComponentType.NEUTRON上构建的粒子,其中ComponentType是包含质量的enum

后来我想做一个ParticleFactory类,它对应于GUI下拉列表中的基本粒子列表。就像:ParticleFactory(Hydrogen)会给我一个包含{ComponentType.ELECTRON, ComponentType.PROTON}列表的粒子对象。这将使修改变得容易,因为ParticleFactory和GUI将对基本粒子使用相同的enum

当我尝试实现它时出现了问题。我知道使用不正确的语法是不可能的,但是无论我做什么我总是会出错。

public enum GenericParticleType {

ELECTRON({"electron","e"}, new ArrayList<ComponentType>());

private final String[] names;
private final List<ComponentType> components;

GenericParticleType(String[] names, List<ComponentType> components) {
    this.names = names;
    this.components = components;
    }
}


目的是使enum包含其他enums的列表。 :D有任何适当的方法吗?

也许有更好的方法吗?常数HashMap

最佳答案

我认为您需要以下设计:


名为GenericParticle的接口。
给出最基本实现的枚举。
您可以在这里进行所需的工厂/建造商。


您可以使用以下代码实现此目的:

enum Component {
    ELECTRON, PROTON, NEUTRON;
}

interface GenericParticle {
    List<String> getNames();

    List<Component> getComponents();
}

enum BasicGenericParticle implements GenericParticle {
    ELECTRON(
            Arrays.asList("electron", "e"),
            Arrays.asList(Component.ELECTRON)
    ),
    HYDROGEN(
            Arrays.asList("hydrogen", "h"),
            Arrays.asList(Component.ELECTRON, Component.PROTON)
    )
    ;

    private final List<String> names;
    private final List<Component> components;

    private BasicGenericParticle(final List<String> names, final List<Component> components) {
        this.names = names;
        this.components = components;
    }

    @Override
    public List<String> getNames() {
        return new ArrayList<>(names);
    }

    @Override
    public List<Component> getComponents() {
        return new ArrayList<>(components);
    }
}

class GenericParticleBuilder {
    private List<String> names = new ArrayList<>();
    private List<Component> components = new ArrayList<>();

    public GenericParticleBuilder name(final String name) {
        names.add(name);
        return this;
    }

    public GenericParticleBuilder component(final Component component) {
        components.add(component);
        return this;
    }

    public GenericParticle build() {
        return new GenericParticleImpl(names, components);
    }

    private static class GenericParticleImpl implements GenericParticle {
        private List<String> names = new ArrayList<>();
        private List<Component> components = new ArrayList<>();

        public GenericParticleImpl(final List<String> names, final List<Component> components) {
            this.names = names;
            this.components = components;
        }

        @Override
        public List<String> getNames() {
            return new ArrayList<>(names);
        }

        @Override
        public List<Component> getComponents() {
            return new ArrayList<>(components);
        }
    }
}


用作:

    GenericParticle electron = BasicGenericParticle.ELECTRON;
    GenericParticle hydrogen = BasicGenericParticle.HYDROGEN;
    GenericParticle water = new GenericParticleBuilder()
            .name("water").name("h2o2")
            .component(/*components*/)
            .build();


您确实需要针对以下事实采取预防措施:


除非客户自己实施GenericParticle,否则任何非法粒子都不能构造,但是为此,您有文档来确保他做正确的事。
防御性复制的性能不是最好的,但是您绝对希望字符串不可变。您可以考虑自己实现一个不可变的列表(不能更改列表中的元素),或者使用诸如guava之类的库提供的(最好)。我不会使用String数组,因为它们会给其他开发人员和您自己带来很多负担,我更喜欢对象。

10-08 11:09