这个简单工厂是否违反开放封闭原则?
每次需要创建新的具体产品时,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());
}
}
这个简单工厂是否违反开放封闭原则?
回答你的问题。 “是的,简单工厂违反开放封闭原则是有原因的。”
应该修改Simple Factory模式,以帮助我们为调用者选择特定的类。如果我们使这个类符合开放封闭原则,那么我们必须将负担转移到其他类,这个类将不再用于工厂的目的。并非所有原则都是绝对的。我们需要权衡使用时或不使用时的好处。
除了Timothy Truckle关于服务定位器的答案...
在Java 8中,您可能希望使用method references和Supplier
接口来实现像您这样的简单用例的通用工厂。
EG
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:通过更多的重构,你可以简单地将它变成任何类型的真正通用工厂。
开放/封闭原则并不真正适用于工厂,因为毕竟它们是不同类型对象的来源......
另一方面,你可以让一个抽象工厂使用javas ServiceLoader查找“真正的”工厂。然后你可以在自己的罐子里添加更多真正的工厂而不用改变现有的代码......
上面给出的静态工厂示例仍可扩展到冰淇淋等其他产品,如下所示。即使我们使工厂metod静止仍然可以扩展(虽然不是通过覆盖方法)
class SimpleProductFactoryExt extends SimpleProductFactory {
public Product createProduct(String productName) {
if (productName.equals("Icecream")) {
return new Milk();
} else {
return super.createProduct(productName);
}
}
}