vendredi 24 février 2017

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

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!

Aucun commentaire:

Enregistrer un commentaire