nir*_*ali 2 java reflection factory-pattern open-closed-principle
我正在尝试使用Head First Design Pattern学习面向对象的设计模式.这是本书中工厂模式的一个例子,我想在不违反开放封闭原则的情况下添加新的披萨项目.在书中给出的示例代码中,如果我添加新的披萨项类,我需要修改PizzaStore和PizzaOrder类.但我只是想添加新的Pizza Item而不修改其他类.
public class ChicagoPizzaStore extends PizzaStore {
Pizza createPizza(String item) {
if (item.equals("cheese")) {
return new ChicagoStyleCheesePizza();
} else if (item.equals("veggie")) {
return new ChicagoStyleVeggiePizza();
} else if (item.equals("clam")) {
return new ChicagoStyleClamPizza();
}
else return null;
}
Run Code Online (Sandbox Code Playgroud)
}
这个pizzaStore类是创建和订购披萨.
public abstract class PizzaStore {
abstract Pizza createPizza(String item);
public Pizza orderPizza(String type) {
Pizza pizza = createPizza(type);
System.out.println("--- Making a " + pizza.getName() + " ---");
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
Run Code Online (Sandbox Code Playgroud)
}
这是抽象的Pizza课程:
public abstract class Pizza {
String name;
String dough;
String sauce;
ArrayList toppings = new ArrayList();
void prepare() {
System.out.println("Preparing " + name);
System.out.println("Tossing dough...");
System.out.println("Adding sauce...");
System.out.println("Adding toppings: ");
for (int i = 0; i < toppings.size(); i++) {
System.out.println(" " + toppings.get(i));
}
}
Run Code Online (Sandbox Code Playgroud)
此类用于从客户处获取订单.
public class PizzaTestDrive {
public static void main(String[] args) {
PizzaStore nyStore = new NYPizzaStore();
PizzaStore chicagoStore = new ChicagoPizzaStore();
Pizza pizza = nyStore.orderPizza("cheese");
System.out.println("Ethan ordered a " + pizza.getName() + "\n");
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的新披萨项目类.我想订购这个披萨项而不修改chicagoPizzaStore和testDrive类:
public class ChicagoStyleClamPizza extends Pizza {
public ChicagoStyleClamPizza() {
name = "Chicago Style Clam Pizza";
dough = "Extra Thick Crust Dough";
sauce = "Plum Tomato Sauce";
toppings.add("Shredded Mozzarella Cheese");
toppings.add("Frozen Clams from Chesapeake Bay");
}
void cut() {
System.out.println("Cutting the pizza into square slices");
}
}
Run Code Online (Sandbox Code Playgroud)
就目前而言,每次ChicagoPizzaStore出现一种新型披萨(新的子类Pizza)时,您需要为具体的创建者方法添加更多功能,createPizza(String item)以使Pizza商店能够创建这些类型的披萨.
如您所知,这违反了OCP.
以下是该问题的两种解决方案.
1.使用内部反射createPizza(String item)动态创建比萨饼
此解决方案将要求您最后一次违反OCP的原则,但是使用反射动态创建Pizza实例意味着ChicagoPizzaStore,除了此更改之外,不再需要修改以支持未来的Pizza风味.
新类型Pizza的名称必须与提供给create pizza方法的键(item参数)的名称相匹配.解决方案的工作原理如下:
public class ChicagoPizzaStore extends PizzaStore {
Pizza createPizza(String item) {
try {
//some assumptions about the classpath locations made here
return Class.forName(item).newInstance();
} catch(Exception e) {
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
Pizza创建新类型时,可以简单地将这些类型作为createPizza(item)方法的键传递,然后创建它们.
类似地,如果Pizza从菜单中取出一种类型,从类路径中删除这样一个Pizza的类定义将导致createPizza(item)为discountinued flavor返回null.
由于各种原因,反思的使用受到了批评,但对反思的批评超出了这个问题的范围,而且对于实施坚持开放/封闭的工厂的问题来说,这是一个完全有效的解决方案.原理.
2.子类ChicagoPizzaStore
作为SOLID状态中的O,类是"可以扩展并关闭以进行修改".因此,解决您的问题只是扩展ChicagoPizzaStore:
public class ExtendedChicagoPizzaStore extends ChicagoPizzaStore {
Pizza createPizza(String item) {
if (item.equals("spicy")) {
return new RidiculouslySpicyPizza();
} else {
return super.createPizza(item);
}
}
Run Code Online (Sandbox Code Playgroud)
该解决方案的优点是不会违反OCP以便应用它.
| 归档时间: |
|
| 查看次数: |
3470 次 |
| 最近记录: |