这个简单的工厂违反开放封闭原则吗?

时间:2017-12-31 15:40:05

标签: java oop design-patterns solid-principles design-principles

这个简单工厂是否违反开放封闭原则?

每次需要创建新的具体产品时,SimpleProductFactory都需要更改,但它遵循单一责任原则,因为这是它永远改变的唯一原因。它的唯一目的是让客户不违反开放的封闭原则,所以我认为它本身不会违反,因为很明显这个代码是需要的。

我对更改工厂不感兴趣,但这个具体示例是否违规。

产品

interface Product{
  public int getPrice();
}

class Milk implements Product{
  public int getPrice(){ return 5; }
}

芯片

class Chips implements Product{
  public int getPrice(){ return 3; }
}

SimpleProductFactory

class SimpleProductFactory{

  public Product createProduct(String productName){

    if(productName.equals("milk")){
      return new Milk();
    }
    else if(productName.equals("chips")){
      return new Chips();
    }
    return null;
  }
}

客户端

class Client{
  public static void main(String[] args) {
    SimpleProductFactory productFactory = new SimpleProductFactory();
    Product prod = productFactory.createProduct("milk");
    System.out.println(prod.getPrice());

  }
}

4 个答案:

答案 0 :(得分:2)

  

这个简单工厂是否违反开放封闭原则?

回答你的问题。 "是的,简单工厂违反了开放封闭原则的原因。"

应该修改Simple Factory模式,以帮助我们为调用者选择特定的类。如果我们使这个类符合开放封闭原则,那么我们必须将负担转移到其他类,这个类将不再用于工厂的目的。并非所有原则都是绝对的。我们需要权衡使用时或不使用时的好处。

答案 1 :(得分:2)

除了关于服务定位器的Timothy Truckle回答......

在Java 8中,您可能希望使用method referencesSupplier接口为像您这样的简单用例实现通用工厂。

E.g。

class SimpleProductFactory {

    private Map<String, Supplier<? extends Product>> supplierRegistry = new HashMap<>();

    public void addProductSupplier(String productName, Supplier<? extends Product> productSupplier) {
        supplierRegistry.put(productName, productSupplier);
    }

    public Product createProduct(String productName) {
        Product product = null;

        Supplier<? extends Product> productSupplier = supplierRegistry.get(productName);

        if (productSupplier != null) {
            product = productSupplier.get();
        }

        return product;
    }
} 

您的客户端代码将如下所示

class Client{
  public static void main(String[] args) {
    SimpleProductFactory productFactory = new SimpleProductFactory();

    productFactory.addProductSupplier("milk", Milk::new); // Constructor reference
    productFactory.addProductSupplier("chips", Chips::new);

    Product prod = productFactory.createProduct("milk");
    System.out.println(prod.getPrice());

  }
}

正如您所见,简单的工厂是

  • 打开以进行扩展,因为您可以简单地添加其他产品供应商
  • 已关闭进行修改,因为您在实施其他产品时无需更改,只需添加即可。

PS:通过更多的重构,你可以简单地将它变成任何类型的真正通用工厂。

答案 2 :(得分:0)

开放/封闭原则并不真正适用于工厂,因为它们毕竟是不同类型对象的源头......

另一方面,您可以使用javas strtotime使用抽象工厂查找“真正的”工厂。那么你可以在不更改现有代码的情况下添加更多真正的工厂,而不需要改变现有的代码......

答案 3 :(得分:0)

上面给出的静态工厂示例仍可扩展到冰淇淋等其他产品,如下所示。即使我们使工厂metod静止仍然可以扩展(虽然不是通过覆盖方法)

    class SimpleProductFactoryExt extends SimpleProductFactory {
        public Product createProduct(String productName) {
            if (productName.equals("Icecream")) {
                return new Milk();
            } else {
                return super.createProduct(productName);
            }
        }
    }