Patterns: Be independent of different subclasses by passing an Object array to the constructor

谁都会走 提交于 2020-01-07 07:42:09

问题


Let's say I load a whole lot of entities from a file. Most of these entities (Not all of them) are of a different class type, and thus may (Or may not) have a different constructor. However, all of them share one superclass: Entity.class

How bad/good is it to let the superclass have one constructor public Entity(Object[] args);, so that the arguments will simply also be loaded from file and passed to the constructor, where the constructor then sorts out what exactly to do with that array?

The main reason I even want to do something like this is because I want to avoid huge switch-statements, where I have to first check what class I am loading and then check the arguments as well.

Basically, let's say I have the following data-structure (Assuming keys can have duplicates!)

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

Loaded from a similar-looking XML file:

<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>

I would then use it somehow like the following:

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

Each entity class could thus simply work like this:

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

I know - I'm using way too much reflection, and, looking at the design of this whole thing, it does look quite bad. However, the only alternative I see is using something like this (Still using the same data-structure & XML)

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

The main problem I have with this kind of structure: I can't make my app modular. I can't simply make a small plugin system allowing me to plug-in new Entity Types with time, and then properly load them from a new XML, since I have to change this loading code as well. My goal is to avoid doing exactly that!

I'd also want to avoid using reflection, though.

So... What do I do? Or, what can I do?

Thanks!


回答1:


It would be horribly, frustratingly bad to do that.

Without looking at your class and class implementation, how do you figure out what actually needs to go into the constructor?

You don't know, and that is frustrating when programming.

Have explicit parameters in your constructor to help show your class' intent.

I strongly recommend you to look at Uncle Bob's book Clean Code. He will give a much better explanation of why I recommend naming all your parameters.



来源:https://stackoverflow.com/questions/42446144/patterns-be-independent-of-different-subclasses-by-passing-an-object-array-to-t

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!