【问题标题】:Factory Pattern: Supporting new concrete types工厂模式:支持新的具体类型
【发布时间】:2019-03-11 17:23:24
【问题描述】:

我在this 链接中研究Factory Pattern。 在编写了一个普通的工厂之后,作者继续设计一个工厂,我们不必修改工厂的代码来添加新的具体实现。 (假设有一个Product 接口,工厂提供了它的实现)。

为了实现这一点,作者说:

我们在产品抽象类中添加了一个新的抽象方法。每个具体类都将实现此方法以创建与自身相同类型的新对象。

这个代码sn-p如下:

 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();
    }
}

我有一个疑问。我们已经在工厂注册了一个 OneProduct 的instance。然后在运行时,我们调用createProduct() 方法再次创建Oneproduct 的新实例。

这是正确的做法吗?我们必须在这里创建OneProduct两个实例,我觉得这是错误的。

【问题讨论】:

  • 我猜这个解决方案是在 Java 8 之前设计的。在 Java 8 中,您可能可以改用 Supplier<Product>
  • 我不相信那个叫字段m_RegisteredProducts的人,这篇文章似乎过时了

标签: java oop design-patterns factory-pattern


【解决方案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&lt;Product&gt;的小对象,您可以在其上调用get(),它将使用默认构造函数创建一个新产品。

你提到的文章很老了。我相信它早于 Java 1.2,因为它仍然使用 Hashtable 而不是现代地图,并且没有泛型。原则保持不变,但有更现代的实施方式。

【讨论】:

  • 我认为实例必须与它创建的类型相同。
  • 不,没有真正的理由。其实文中最后一个解决方案——每个混凝土产品都有一个混凝土工厂是完全一样的。
  • However, it's not necessary that the instance will be of the same type that it creates 。我认为这是我的主要收获。谢谢你的解释!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-17
  • 2013-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多