在某些存在类层次结构并且最顶层的基类是抽象类的地方,抽象类中有一个静态getInstance()方法。这将负责创建正确的子类并将其返回给调用者。例如,请考虑以下代码。
public class abstract Product {
public static Product getInstance(String aCode) {
if ("a".equals(aCode) {
return new ProductA();
}
return ProductDefault();
}
// product behaviour methods
}
public class ProductA extends Product {}
public class ProductDefault extends Product {}
在Java中,java.util.Calendar.getInstance()是一个遵循此模式的地方。但是,这意味着每次引入新的子类时都必须修改基类。即:在上面的例子中必须修改产品类。这似乎违反了ocp原则。基类也知道子类的详细信息,这也是个问题。
我的问题是......
答案 0 :(得分:4)
界面不是反模式。但是你实现它的方式相当差......因为你确定的原因。更好的想法是为每个代码注册工厂对象的一些机制:
Java类库使用SPI和代码执行此类操作,这些代码反映了要动态加载的“提供程序”类。
更简单的方法是使用“注册表”对象,并使用依赖注入或工厂对象类中的静态初始化程序填充它,或者从属性文件中读取类名的启动方法等。< / p>
答案 1 :(得分:2)
不,不是。它更像factory method pattern
http://en.wikipedia.org/wiki/Factory_method_pattern。例如。 Calendar.getInstance();
。 JDK充满了这样的例子。还提醒有效Java Item 1: Consider static factory methods instead of constructors
答案 2 :(得分:2)
这里有许多不同的问题。
getInstance
可能是个坏名字。你明确地想要一个可以玩的新对象。 “创造”,“制造”,“新”或只是留下这个词。在这种情况下,“实例”也是一个非常空洞的词。如果类名中有足够的上下文,请将其删除,否则说出它是什么,即使它只是一个类型名称。如果该方法返回一个不可变对象,则of
是约定(在过去的时间valueOf
)。
如所确定的那样,将它放在抽象基类中(或者如果可能的话,在接口中)并不是最好的主意。在某些情况下,所有可能的子类型的枚举都是合适的 - 如果你打算使用访问者,那么明显而且真的不是那么糟糕。最好把它放在一个新文件中。
与可变静力学有关的任何事情都是错误的。它是否重用相同的可变实例,注册或做一些令人厌恶的当前线程。不要做或依赖(直接或间接)任何事情。
答案 3 :(得分:0)
根据反馈,我介绍了一个新的ProductFactory类,负责创建正确的Product。在我的情况下,正确的产品实例的创建取决于外部上下文(我为了简单起见而放置产品代码..在实际情况下,它可能基于几个参数......这些可能随着时间的推移而变化)。因此,由于问题中概述的原因,使用Product.getInstance()方法并不合适。同样具有不同的ProductFactory意味着将来。如果需要,产品类可以成为一个接口。它只是提供了更多的可扩展性。
我认为当对象的创建不依赖于外部上下文时...就像Calendar.getInstance()一样,拥有这样的方法是完全可以的。在这些情况下,找到正确实例的逻辑是该特定模块/类的内部逻辑,并且不依赖于任何外部提供的信息。