一、定义
工厂方法模式:定义了一个创建对象的借口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
模式组成元素:
创建者(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)开始。
四、总结