我可能使用了错误的单词,所以当我说Business Object(BO)时,我的意思是一个类,它引用了映射到具有Hibernate的数据库表的类,以及业务逻辑。
我面临的问题是在不使用反射或instanceof的情况下为子类实例化正确的BO。
例如,假设我有一个Pen-table,其中只有一个对Animal-table的引用,而table-table又有两个子表Cat和Dog(所有一对一引用)。这些类看起来像这样:
public class Pen {
private Animal a;
// Getters and setters
}
public class Animal {
// Getters and setters
}
public class Dog extends Animal {
// Getters and setters
}
public class Cat extends Animal {
// Getters and setters
}
public class PenBO {
private Pen p;
public AnimalBO getAnimalBO() { ... }
}
public interface Action {
void visit(DogBO dbo);
void visit(CatBO cbo);
}
public class Sound implements Action {
void visit(DogBO dbo) { ... }
void visit(CatBO cbo) { ... }
}
public interface AnimalBO {
void accept(Sound s);
}
public class DogBO implements AnimalBO {
Dog d;
void accept(Sound s) {
s.visit(this);
}
}
public class CatBO implements AnimalBO {
Cat c;
void accept(Sound s) {
s.visit(this);
}
}
然后我只使用BO在BO的get-methods中实例化它们:
Pen p = ... // Get or load from database
PenBO pbo = new PenBO();
pbo.setPen(p);
然后我使用这样的类:
pbo.getAnimalBO().accept(new Sound());
这是我正在研究的getAnimalBO方法。我希望它基于Pen的Animal-instance返回BO的正确实例。
我“可以”使用instanceof检查来自当前Pen的实际Animal,但这显然不是很好。我想到的另一种选择是使用反射来获取类名并在之后添加“BO”并得到一个实例,但它也非常难看。
我尝试在getAnimalBO周围包装另一个访问者模式但是它不能在没有强制转换的情况下选择正确的访问方法,我不想在非BO类中添加accept-methods。
如果没有聪明的方法让这种方法有效地工作,那么核心问题是什么?我还没有找到任何Hibernate的最佳实践。 Hibernate和访问者模式的一些例子只是将accept-methods添加到映射的类中,这可能不是很好......
答案 0 :(得分:1)
您的问题实际上只是继承的OO问题,并且从一个类层次结构转换为并行层次结构。你已经解决了这个和Hibernate映射的数据库建模,显然你的访问者实现没有任何问题。只是您不希望将访问者模式应用于映射的类层次结构,因此您在两个层次结构之间进行转换时遇到了问题。
就目前情况而言,代码的一部分必须负责知道CatBO
对应Cat
等,并知道Pen
对象的{{{} 1}}属性实际上是Animal
,然后包含Cat
对象的PenBO
属性实际上是AnimalBO
。鉴于此,它必须能够确定返回的CatBO
实例的类型,因此我无法看到如何避免使用Animal
或反射之一。你对instanceof
的反对意见是什么?获得课程名称和附加“BO”的反思是非常讨厌和丑陋的,我同意,尽管它显然可以起作用。但是一个方法,其责任是instanceof
并使用Animal
返回合适的AnimalBO
并选择正确的instanceof
类并不是坏事IMHO。
我要问的问题是你为什么要从一个类层次结构映射到另一个类层次结构。您已经说过想要将BO
方法添加到映射的类中,并且“不能很好”,但是你没有理由为什么你有这种感觉。它是否比您自己提出的选项更糟糕?通过将访问者模式添加到映射的类层次结构中,您实际上并未在其中嵌入任何业务逻辑,而只是使用访问者模式在层次结构中启用业务逻辑应用程序。因此,您的业务逻辑层包含简单的通用访问者实现,您的映射类或域层是POJO加上基本的访问者实现,并且您实际上确实拥有我认为您想要的清晰分离。