1

I am searching for a design pattern to generate objects from a template object. In my game i have different kind of items which will be generated out of a template object.

Currently i solved it by inheritance where each template entity implements the method:

   public Item generate(EntityManager em);

My inheritance structure is:

    ItemTemplate                  -> creates an Item
         |_ ArmorTemplate         -> creates and Armor
         |_ WeaponTemplate        -> creates an Weapon
         |_ ....and more ....

When i create a item i pass the entity manager to the template and i get a persisted object. E.g. an ArmorTemplate returns me a persisted Armor and so on.

If the item generation needs any specific entities i have to do a lookup inside the generation method. I would like to solve it with a container based solution where i can inject my needed EJBs and do not have to pass my entity manager through the creation workflow.

From Hibernate i get a List of template objects and i do not want to do a instanceof to call the correct factory method.

My current solution works, but feels not very elegant. Any input would be fine. ;-)

Thanks in advance. greetings, m

mkuff
  • 1,620
  • 6
  • 27
  • 39
  • How different is your current implementation from the Factory pattern? – Vineet Reynolds Aug 11 '11 at 20:27
  • Well it is a factory pattern where each template knows which object it has to return and how. But i wounder if the pojo style can be replaced with a ejb solution to receive the benefits of dependency injection and so on. – mkuff Aug 11 '11 at 20:38
  • What do you mean with this: "From Hibernate i get a List of template objects and i do not want to do a instanceof to call the correct factory method." If the Template objects are just factories, i would just wire them as singleton services with a Reference to the entity Manager. – tkr Aug 11 '11 at 21:13
  • Do determine which Items are in a ingame-container which is opened for the first time i select all template objects which are assigned to it. So i have this list of ItemTemplate objects and i generate my items from it and add it into the container that the player can pick it up. So my templates are stored in the db and assigned to various containers where they can pop out ingame. – mkuff Aug 12 '11 at 06:45

1 Answers1

3

It is not possible to inject EJBs into the template objects as long they are domain objects with Java EE:

Inject EJB into domain object with Java EE 6

It is possible with spring:

http://java.dzone.com/articles/domain-object-dependency-injection-with-spring

I would however probably try to split the template domain object from the object persiting part. (just for my understanding: the ArmorTemplate is some kind of armor and there are multiple different with varying attributes, each ArmorItem is one instance of exactly one ArmorTemplate and there can be multiple items for one template)

Here is a suggestion. The complicated generic part is to enable, that an ArmorItem can only by build by an ArmorTemplate and that you can access specific properties from this template without cast.

static abstract class Item<I extends Item<I, T>, T extends ItemTemplate<I, T>> {
    T template;
}
static abstract class ItemTemplate<I extends Item<I, T>, T extends ItemTemplate<I, T>> {
    abstract I createItem();
}

// JPA Domain Objects:
static class Armor extends Item<Armor, ArmorTemplate> {}
static class ArmorTemplate extends ItemTemplate<Armor, ArmorTemplate> {
    public final int hitpoints;

    public ArmorTemplate(int hitpoints) {
        this.hitpoints = hitpoints;
    }

    @Override
    Armor createItem() {
        return new Armor();
    }
}

// This POJO can be CDI managed
static class ItemDao {
    // @Inject public EntityManager em;

    public <I extends Item<I, T>, T extends ItemTemplate<I, T>> 
    List<I> createItemsFromTemplates(List<T> templates) {
        List<I> result = new ArrayList<I>();
        for (T template : templates) {
            I item = template.createItem();
            item.template = template;
            // em.persist(item);
            result.add(item);
        }
        return result;
    }
}

public static void main(String[] args) {
    List<ArmorTemplate> armorTemplates = Arrays.asList(
            new ArmorTemplate(100), new ArmorTemplate(80));

    List<Armor> armorItems = new ItemDao().createItemsFromTemplates(armorTemplates);

    for (Armor armor : armorItems) {
        System.out.println(armor.template.hitpoints);
    }
}
Community
  • 1
  • 1
tkr
  • 1,331
  • 1
  • 9
  • 27
  • Yes, that what i meant. My question is how to split it without to determine the exact type? – mkuff Aug 12 '11 at 06:18
  • Very interesting solution! I will experiment with it and deside if it fits better. Thank you!# – mkuff Aug 12 '11 at 16:07