一、定义
工厂方法模式:定义了一个创建对象的借口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
模式组成元素:
创建者(Creator)类:
- 创建抽象创建者类,定了一个抽象的工厂方法,让子类实现此方法而制造产品。
- 创建者通常会包含依赖于抽象产品的代码,而这些抽象产品由子类创造。创建者不需要真的知道在制造哪种具体产品。
产品类:
- 创建抽象产品类,所有产品必须实现公共接口
二、疑惑
三、实现
import java.util.ArrayList;; public abstract class Pizza { String name; String dough; //dough 生面团 String sauce; //sauce 酱油 ArrayList toppings = new ArrayList(); //topping 糕点上的装饰配料 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)); } } void bake(){ System.out.println("Bake for 25 minutes at 350"); } void cut(){ System.out.println("Cutting the pizza into diagonal slices"); } void box(){ System.out.println("Place pizza in official PizzaStore box"); } public String getName(){ return name; } } public abstract class PizzaStore { public Pizza orderPizza(String type){ Pizza pizza; pizza = createPizza(type); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; } abstract Pizza createPizza(String type); //实现了实际制造产品 } public class NYPizzaStore extends PizzaStore{ Pizza createPizza(String item){ if(item.equals("cheese")){ return new NYStyleCheesePizza(); } else return null; } } public class ChicagoPizzaStore extends PizzaStore{ Pizza createPizza(String item) { if(item=="cheese") return new ChicagoStyleCheesePizza(); else return null; } } public class NYStyleCheesePizza extends Pizza{ //cheese 奶酪 public NYStyleCheesePizza(){ name="NY Style Sauce and Cheese Pizza"; dough = "Thin Crust Dough"; sauce = "Marinara Sauce"; toppings.add("Grated Reggiano Cheese"); } } public class ChicagoStyleCheesePizza extends Pizza{ public ChicagoStyleCheesePizza(){ name = "Chicago Style Deep Dish Cheese Pizza"; // dough = "Extra Thick Crust Dougn"; //厚饼 sauce = "Plum Tomato Sauce"; toppings.add("Shredded Mozzarella Cheese"); } void cut(){ //覆盖cut()方法 System.out.println("Cutting the pizza into square slices"); } } 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"); pizza= chicagoStore.orderPizza("cheese"); System.out.println("Joel ordered a "+ pizza.getName()+"\n"); } }
输出
Preparing NY Style Sauce and Cheese Pizza
Tossing dough...
Adding sauce...
Adding toppings:
Grated Reggiano Cheese
Bake for 25 minutes at 350
Cutting the pizza into diagonal slices
Place pizza in official PizzaStore box
Ethan ordered a NY Style Sauce and Cheese PizzaPreparing Chicago Style Deep Dish Cheese Pizza
Tossing dough...
Adding sauce...
Adding toppings:
Shredded Mozzarella Cheese
Bake for 25 minutes at 350
Cutting the pizza into square slices
Place pizza in official PizzaStore box
Joel ordered a Chicago Style Deep Dish Cheese Pizza
四、依赖倒置原则
1、定义
不能让高层组件依赖于底层组件,而且,不关高层或底层组件,两者都应该依赖于抽象。
2、设计原则
- 要依赖于抽象,而不依赖于具体类
- 变量不可以持有具体类的引用(如果new,就会持有具体类的引用)
- 不要让类派生子具体类(如果派生自具体类,就会依赖于具体类。要派生自抽象(接口或抽象类))
- 不要覆盖基类中以实现的方法(如果基类已实现方法,那么基类就不是一个真正适合被继承的抽象。基类中以实现的方法,应该让子类共享)
3、实例分析
高层组件(PizzaStore)和底层组件(即Pizza)都依赖于Pizza抽象。想要遵循依赖倒置原则,工厂方法并非是唯一技巧,但确实最好用的技巧之一。
4、理解
- 倒置,指别从顶端(工厂)开始思考设计,而是从底层(Pizza)开始。
四、总结