这个简单工厂是否违反开放封闭原则?
每次需要创建新的具体产品时,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());
}
}
答案 0 :(得分:2)
这个简单工厂是否违反开放封闭原则?
回答你的问题。 "是的,简单工厂违反了开放封闭原则的原因。"
应该修改Simple Factory模式,以帮助我们为调用者选择特定的类。如果我们使这个类符合开放封闭原则,那么我们必须将负担转移到其他类,这个类将不再用于工厂的目的。并非所有原则都是绝对的。我们需要权衡使用时或不使用时的好处。
答案 1 :(得分:2)
除了关于服务定位器的Timothy Truckle回答......
在Java 8中,您可能希望使用method references和Supplier
接口为像您这样的简单用例实现通用工厂。
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);
}
}
}