我正在寻找一种设计模式来从模板对象生成对象。在我的游戏中,我有不同类型的项目,这些项目将由模板对象生成。
目前我通过继承来解决它,其中每个模板实体实现该方法:
public Item generate(EntityManager em);
我的继承结构是:
ItemTemplate -> creates an Item
|_ ArmorTemplate -> creates and Armor
|_ WeaponTemplate -> creates an Weapon
|_ ....and more ....
当我创建一个项目时,我将实体管理器传递给模板,然后我得到一个持久化对象。 例如。 ArmorTemplate给我一个持久的护甲等等。
如果项目生成需要任何特定实体,我必须在生成方法中进行查找。我想用基于容器的解决方案解决它,我可以注入我需要的EJB,而不必通过创建工作流程传递我的实体管理器。
从Hibernate我得到一个模板对象列表,我不想做一个instanceof来调用正确的工厂方法。
我目前的解决方案有效,但感觉不是很优雅。任何输入都没问题。 ; - )
提前致谢。 问候,m
答案 0 :(得分:3)
只要EJB是具有Java EE的域对象,就不可能将EJB注入模板对象:
Inject EJB into domain object with Java EE 6
春天有可能:
http://java.dzone.com/articles/domain-object-dependency-injection-with-spring
但是,我可能会尝试从对象持久部分中分离模板域对象。 (仅供我理解:ArmorTemplate是某种盔甲,有多种不同的属性,每个ArmorItem只有一个ArmorTemplate的一个实例,一个模板可以有多个项目)这是一个建议。复杂的通用部分是启用,ArmorItem只能通过ArmorTemplate构建,并且您可以从此模板访问特定属性而无需强制转换。
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);
}
}