我有四种类型的数据对象:
class DataTypeAlpha extends DataType
class DataTypeBeta extends DataType
class DataTypeGamma extends DataType
class DataTypeDelta extends DataType
以及来自 GUI 框架的四种不同的 TreeNode 类型,每一种都特定于包装的 DataType:
class AlphaTreeNode extends MyAppTreeNode
...
现在我经常遇到这样的模式:我有一个 DataType 实例,但需要一个新的 MyAppTreeNode 实例。我看到两个解决方案。解决方案一:
class DataType {
// Instantiates and returns the appropriate MyAppTreeNode for this DataType
abstract MyAppTreeNode createTreeNode();
}
解决方案二:
class MyAppTreeNode {
static MyAppTreeNode createTreeNodeForDataType(DataType dataType) {
if(dataType instanceOf DataTypeAlpha) return new AlphaTreeNode((DataTypeAlpha)dataType)
else if (dataType instanceOf DataTypeBety) return new BetaTreeNode((DataTypeBeta)dataType)
else if ...
else if ...
else throw new IllegalArgumentException();
}
}
解决方案一使用多态性,更短,更“优雅”。但我希望 DataType 类不了解我使用的 GUI 框架。也许我什至可以使用两个不同的 GUI 框架?
您看到第三种解决方案吗?我在这个问题中添加了 Guice 标签。也许 Guice 或其他依赖注入(inject)库中有一些函数可以在这里提供帮助?
查看类似的问题:
- 当然,我会为此使用工厂模式,但在工厂内部我仍然有问题。
最佳答案
为此,您可以使用受访客启发的方法。与往常一样,所有 DataType 对象都有一个 accept
方法,但与普通访问者模式相反,它不会遍历子对象,并且会返回一个值。为了避免太多困惑,让我们为 operator
而不是 visitor
调用传递给 accept
的对象。诀窍是让 accept
和 operators
返回泛型类型。
所以数据模型中的代码将是这样的
public abstract class DataType {
public abstract <T> T accept(Operator<T> op);
}
public interface Operator<T> {
T operateAlpha(DataTypeAlpha data);
T operateBeta(DataTypeBeta data);
...
}
public class DataTypeAlpha extends DataType {
public <T> T accept(Operator<T> op) {
return op.operateAlpha(this);
}
}
....
在 GUI 中您将拥有
public class TreeNodeFactory implements Operator<MyAppTreeNode> {
public MyAppTreeNode operateAlpha(DataTypeAlpha data) {
return new AlphaTreeNode(data);
}
...
}
public class MyAppTreeNode {
static TreeNodeFactory factory = ...;
static MyAppTreeNode createTreeNodeForDataType(DataType dataType) {
return dataType.accept(factory);
}
}
关于java - 根据构造函数参数实例化特定的子类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17230283/