2

In some places where a class hierarchy is present and the top most base class is an abstract class there is a static getInstance() method in the abstract class. This will be responsible for creating the correct sub-class and returning it to the caller. For example consider the below code.

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 {}

In Java, java.util.Calendar.getInstance() is one place this pattern has been followed. However this means each time a new subclass is introduced one has to modify the base class. i.e: Product class has to be modified in the above example. This seems to violate the ocp principle. Also the base class is aware about the sub class details which is again questionable.

My question is...

  1. is the above pattern an anti-pattern ?
  2. what are the draw-backs of using the above pattern ?
  3. what alternatives can be followed instead ?
4

4 回答 4

4

接口不是反模式。但是你实现它的方式相当糟糕......因为你确定的原因。一个更好的主意是为每个代码注册一些工厂对象的机制:

  • Java 类库使用 SPI 和代码来做这种事情,这些代码反射性地寻找要动态加载的“提供者”类。

  • 一种更简单的方法是拥有一个“注册表”对象,并使用依赖注入或工厂对象类中的静态初始化程序或从属性文件读取类名的启动方法等来填充它。

于 2013-05-04T06:20:29.643 回答
2

这里有许多单独的问题。

getInstance可能会是一个坏名声。您明确想要一个可以玩弄的新对象。“创造”、“制造”、“新”或者干脆不说这个词。在这种情况下,“实例”也是一个相当空洞的词。如果类名中有足够的上下文,请忽略它,否则即使这只是一个类型名,也要说出它是什么。如果该方法返回一个不可变对象,of则为约定(valueOf过去)。

将它放在抽象基类中(或者如果可能的话,放在接口中)并不是最好的主意。在某些情况下,枚举所有可能的子类型是合适的——如果您无论如何都要使用访问者,那么枚举显然而且真的没那么糟糕。最好把它放在一个新文件中。

与可变静态有关的任何事情都是错误的。无论是重用同一个可变实例、注册还是做一些让当前线程恶心的事情。不要这样做或依赖(直接或间接)所做的任何事情。

于 2013-05-04T07:41:12.857 回答
2

No it's not. It's more like factory method pattern http://en.wikipedia.org/wiki/Factory_method_pattern. E.g. Calendar.getInstance();. JDK is full of such examples. Also reminds of Effective Java Item 1: Consider static factory methods instead of constructors

于 2013-05-04T05:54:41.840 回答
0

根据反馈,我引入了一个新的 ProductFactory 类,该类负责创建正确的产品。在我的情况下,正确产品实例的创建取决于外部上下文(为了简单起见,我放置了产品代码......在实际情况下,它可能基于几个参数......这些可能会随着时间而改变)。因此,由于问题中概述的原因,拥有 Product.getInstance() 方法并不适合。未来也有不同的 ProductFactory 意味着.. 如果需要,产品类可以成为接口。它只是提供了更多的可扩展性。

我认为当对象的创建不依赖于外部上下文时......就像在 Calendar.getInstance() 的情况下,拥有这样的方法是完全可以的。在这些情况下,找到正确实例的逻辑是该特定模块/类的内部逻辑,不依赖于任何外部提供的信息。

于 2013-05-11T07:51:03.703 回答