Java 工厂模式与多态性
我的计划是拥有一个Java 工厂模式与多态性,java,polymorphism,factory-pattern,Java,Polymorphism,Factory Pattern,我的计划是拥有一个控制面板工厂,它将为每个不同的模型类构建一个定制的控制面板: abstact class Model { } class ModelA extends Model { } class ModelB extends Model { } 现在,我的计划是让Factory类基于方法重载传递的模型类创建不同的ControlPane实例: class ControlPaneFactory { private ControlPaneFactory() { }
控制面板工厂
,它将为每个不同的模型
类构建一个定制的控制面板
:
abstact class Model {
}
class ModelA extends Model {
}
class ModelB extends Model {
}
现在,我的计划是让Factory类基于方法重载传递的模型
类创建不同的ControlPane
实例:
class ControlPaneFactory {
private ControlPaneFactory() {
}
public static ControlPanel build(ModelA model) {
return new ControlPaneA(model);
}
public static ControlPanel build(ModelB model) {
return new ControlPaneB(model);
}
}
然而,这是非常有问题的,因为在调用factorys方法时,我只有一个Model
类型的变量,因此我需要首先使用instanceof
,这是一个巨大的代码气味。同样适用于采用浓缩工厂法:
public static ControlPane build(Model model) {
if (model instanceof ModelA)
return new ControlPaneA(model);
else if (model instanceof ModelB)
return new ControlPaneB(model);
else throw new IllegalArgumentException("Unsupported model");
}
我曾考虑在模型类中使用枚举来指定model
的类型,但是这似乎也是一个违反DRY的坏选项
此外,我更希望
ControlPane
的实例化独立于Model
类(即在spererate类中)。有没有一种“好”的方法来解决这个问题?试图使您的代码更通用,这意味着您的控制面板不应该依赖于特定的模型。但是,如果确实有必要,您可以尝试以下方法:
public class ControlPanelFactory {
private static Map<Class<? extends Model>, Class<? extends ControlPanel>> modelPanelMap = new HashMap<>();
public static void addModelPaneRelation(Class<? extends Model> model, Class<? extends ControlPanel> pane) {
modelPanelMap.put(model, pane);
}
public static ControlPanel build(Model model) {
try {
return modelPanelMap.get(model.getClass())
.getConstructor(model.getClass())
.newInstance(model);
} catch (Exception exception) {
// Handle exceptions
}
return null;
}
}
至少这将提取面板如何依赖于模型的逻辑。同样,我认为这不是最干净的解决方案。如果您希望所有工厂方法都在同一个对象中,那么您将以某种方式需要If组的开关/实例,或者需要一个
模型
到控制面板
的映射
或者,您可以将factory方法移动到模型
类。本质上,这是抽象工厂模式,但您正在使用模型
对象实现它。有几种方法来看待这个问题。可以说它增加了模型
和控制面板
对之间的耦合,但我建议您尝试实现这一点。也可能有人认为,这会降低factory代码的可重用性,因为您需要一个模型
对象来运行它,但您为factory对象提供的示例接口无论如何都需要一个内置的模型
。随着远离贫血模型,我认为这是一种合理的实现方法,并降低了工厂对象的复杂性(如果您仍然需要的话)
我会这样说:
ControlPanelFactory.addModelPaneRelation(ModelA.class, ControlPanel.class);
abstact class Model {
public abstract ControlPanel buildControlPanel();
}
class ModelA extends Model {
public ControlPanel buildControlPanel() {
return new ControlPanelA(this);
}
}
class ModelB extends Model {
public ControlPanel buildControlPanel() {
return new ControlPanelB(this);
}
}
// Don't really need this anymore...
class ControlPaneFactory {
public static ControlPanel build(Model model) {
return model.buildControlPanel();
}
}
这仍然允许您在需要时为控制面板
灵活地使用不同的构造函数,并且在程序启动时不需要注册对象映射
您可以将buildControlPanel()
方法移出模型
s,创建一个适当的抽象工厂模式,并从模型
对象返回一个具体工厂。但我觉得这只会增加你的课程数量,而不会带来任何实际的改善。如果您有很多使用相同构建代码的Model
类(如ModelA
,ModelB
,ModelC
都对应于ControlPanelX
),那么这可能是一个很好的方法,但听起来您并没有这样做
然而,归根结底,选择要实例化的具体类的switch或if语句并不是世界上最糟糕的事情。其他库也使用了类似的东西,例如。将
ControlPane
的实例化移动到相应的Model
类将是显而易见的解决方案,但正如您所说,这确实增加了视图和模型之间的耦合,这正是我试图避免的。抽象工厂肯定是杀伤力过大。我只是想知道是否有一种明显而优雅的方法可以解决这一问题,但似乎如果你想将控制面板
与模型
分离,总会有一些感觉不太优雅的东西。