工厂模式:支持新的混凝土类型

时间:2019-03-11 17:23:24

标签: java oop design-patterns factory-pattern

我在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两个实例

1 个答案:

答案 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而不是现代地图,并且没有泛型。原则保持不变,但是有更多现代的实现方式。