我在this链接中研究了Factory Pattern
。
编写完正常的工厂后,作者继续设计工厂,而无需修改工厂代码来添加新的具体实现。 (假设有一个Product
接口,并且工厂提供了它的实现。)
为此,作者说:
我们在产品抽象类中添加了一个新的抽象方法。每个具体的类都将实现此方法以创建与自身类型相同的新对象。
此代码段如下:
abstract class Product
{
public abstract Product createProduct();
...
}
class OneProduct extends Product
{
...
static
{
ProductFactory.instance().registerProduct("ID1", new OneProduct());
}
public OneProduct createProduct()
{
return new OneProduct();
}
...
}
class ProductFactory
{
public void registerProduct(String productID, Product p) {
m_RegisteredProducts.put(productID, p);
}
public Product createProduct(String productID){
((Product)m_RegisteredProducts.get(productID)).createProduct();
}
}
我在这里有疑问。我们已经在工厂中注册了一个实例。然后在运行时,我们调用createProduct()
方法,该方法再次创建Oneproduct
的新实例。
这是这样做的正确方法吗?我认为这里是错误的,我们必须创建OneProduct
的两个实例。
答案 0 :(得分:1)
之所以需要两个实例,是因为您在调用createProduct()
方法时正在使用多态。也就是说,每个具体产品都有其自己的createProduct()
实现,并且您可以使用该方法以相同的方式创建所有具体产品,因为它们都继承自同一个抽象类。
但是要做到这一点,您需要有实例。您不能将多态与静态方法一起使用。您只能覆盖实例方法。因此,您需要一个实例来创建一个实例。
但是,实例的类型不必与它创建的类型相同。它只需要是实现所需方法的类的实例。在Java 8中,您可能可以使用Supplier<Product>
得到更干净的解决方案。
abstract class Product
{
...
}
class OneProduct extends Product
{
...
static
{
ProductFactory.instance().registerProduct("ID1", OneProduct::new);
}
...
}
class ProductFactory
{
Map<String,Supplier<Product>> m_RegisteredProducts = new HashMap<>();
public void registerProduct(String productID, Supplier<Product> p) {
m_RegisteredProducts.put(productID, p);
}
public Product createProduct(String productID){
// There should be a null check here...
return m_RegisteredProducts.get(productID).get();
}
}
本质上,方法引用为您提供了一个实现Supplier<Product>
的小对象,您可以在其上调用get()
,这将使用默认构造函数创建新产品。
您提到的文章很老。我相信它早于Java 1.2,因为它仍然使用Hashtable
而不是现代地图,并且没有泛型。原则保持不变,但是有更多现代的实现方式。