模式:通过将Object数组传递给构造函数,使其独立于不同的子类

时间:2017-02-24 18:47:59

标签: java design-patterns reflection constructor load

我想说我从文件中加载了很多实体。大多数这些实体(并非所有实体)都具有不同的类类型,因此可能(或可能不)具有不同的构造函数。但是,它们都共享一个超类:Entity.class

让超类有一个构造函数public Entity(Object[] args);是多么糟糕/好,所以参数也将简单地从文件中加载并传递给构造函数,然后构造函数在那里排序究竟要做什么那个数组?

我甚至想要做这样的事情的主要原因是因为我想避免使用巨大的switch语句,我必须首先检查我正在加载的类,然后检查参数。

基本上,我们说我有以下数据结构(假设密钥可以重复!)

Map<String, ArrayList<String>>
     ^       ^         ^
EntityClass  Params  Parameter (Any type)

从类似外观的XML文件中加载:

<entities>
    <EntityTypeX>
        <parameter>ConstructorArg1</parameter>
        <parameter>42</parameter>
    </EntityTypeX>
    <EntityTypeX>
        <parameter>Whatever bro</parameter>
        <parameter>999</parameter>
    </EntityTypeX>
    <EntityTypeY></EntityTypeY>
    <EntityTypeZ>
        <parameter>myFile.png</parameter>
    </EntityTypeZ>
</entities>

然后我会以某种方式使用它:

for each String className in my map-keys:
    Convert ArrayList to Object[]
    Get class of className, check if it is an entity:
        Invoke it's constructor with the object array

因此,每个实体类都可以像这样工作:

public class EntityTypeX extends Entity {
    String myString; int myNumber;
    public EntityTypeX(Object[] args){
        myString = (String) args[0]; myNumbers = (Integer) args[1];
    }
}

我知道 - 我用过多的反思,并且,看看整个事物的设计,看起来确实很糟糕。但是,我看到的唯一选择是使用类似的东西(仍然使用相同的数据结构和XML)

Entity e;
switch className:
case "EntityTypeX": e = new EntityTypeX((String)objectArray[0], (Integer)objectArray[1]); break;
case "EntityTypeY": ...
case "etc": ...

我对这种结构的主要问题是:我无法使我的应用模块化。我不能简单地创建一个小插件系统,允许我随着时间插入新的实体类型,然后从新的XML中正确加载它们,因为我也必须更改这个加载代码。我的目标是避免这样做!

我也想避免使用反射。

所以...我该怎么办?或者,可以我做什么?

谢谢!

1 个答案:

答案 0 :(得分:0)

这样做会非常糟糕,令人沮丧。

不看你的类和类实现,你如何弄清楚实际需要进入构造函数?

你不知道,编程时这很令人沮丧。

在构造函数中使用显式参数来帮助显示您的课程&#39;意图。

我强烈建议您查看Uncle Bob's book Clean Code。他会更好地解释为什么我建议命名所有参数。