工厂处理创建对象的细节。
一、建立一个简单的比萨工厂
先从工厂本身开始,我们要定义一个类,为所有比萨封装创建对象的代码。简单工厂其实不是一个设计模式,反而比较像是一种编程习惯。
二、声明一个工厂方法
原本是由一个对象负责所有具体类的实例化,现在通过PizzaStore做一些小转变,变成由一群子类负责实例化。
PizzaStore.java
package factorymode.interfac;
public abstract class PizzaStore {
public Pizza orderPizza(String type){
Pizza pizza = null;
pizza = createPizza(type);//PizzaStore的子类在createPizza方法中处理对象的实例化
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
//现在,实例化比萨的责任被移到一个“方法”中,此方法就如同是一个“工厂”
//工厂方法用来处理对象的创建,并将这样的行为封装在子类中。这样,客户程序中关于超类的代码和子类对象创建代码解耦了
protected abstract Pizza createPizza(String type);//抽象方法的好处是,具体的实现由子类来完成
//其他的方法
}
Pizza.java
package factorymode.interfac;
import java.util.ArrayList;
public abstract class Pizza {
protected String name;
protected String dough;
protected String sauce;
protected ArrayList toppings = new ArrayList();
protected 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));
}
}
protected void bake(){
System.out.println("Bake for 25 minites at 350");
}
protected void cut(){
System.out.println("Cutting the pizza into diagonal slices");
}
protected void box(){
System.out.println("Place pizza in official PizzaStore box");
}
public String getName(){
return name;
}
}
需要一些具体子类,来定义纽约和芝加哥风味的芝士比萨fangfa
package factorymode.impl;
import factorymode.interfac.Pizza;
public class NYStyleCheesePizza extends Pizza{
public NYStyleCheesePizza(){
name = "NY Style Sauce and Cheese Pizza";
dough = "Thin Crust Sauce";
sauce = "Marinara Sauce";
toppings.add("Grated Reggiano Cheese");//覆盖的是意大利reggiano高级干奶酪
}
}
package factorymode.impl;
import factorymode.interfac.Pizza;
public class ChicagoStyleCheesePizza extends Pizza {
public ChicagoStyleCheesePizza(){
name = "Chicago Style Deep Dish Cheese Pizza";
dough = "Extra Thick Crust Dough";
sauce = "Plum Tomato Sauce";
toppings.add("Shredded Mozzarella Cheese");
}
protected void cut(){
System.out.println("Cutting the pizza into square slices");
}
}
PizzaStore的实现类
package factorymode.impl;
import factorymode.interfac.Pizza;
import factorymode.interfac.PizzaStore;
public class NYPizzaStore extends PizzaStore {
@Override
protected Pizza createPizza(String type) {
if(type.equals("cheese")){
return new NYStyleCheesePizza();
}else if(type.equals("veggie")){
return new NYStyleVeggiePizza();
}
return null;
}
}
NYPizzaStore生产的pizza。
package factorymode.impl;
import factorymode.interfac.Pizza;
public class NYStyleVeggiePizza extends Pizza{
public NYStyleVeggiePizza(){
name = "NY Style Sauce and veggie Pizza--";
dough = "Thin Crust Sauce--";
sauce = "Marinara Sauce--";
toppings.add("Grated Reggiano Cheese--");//覆盖的是意大利reggiano高级干奶酪
}
}
所有工厂模式都是用来封装对象的创建,工厂方法模式通过让子类决定该创建的对象是什么,来达到将对象创建的过程封装的目的。
图像 小部件
平行的类层级
图像 小部件图像 小部件
三、依赖倒置原则
代码中减少对于具体类的依赖,要依赖抽象,不要依赖具体类。
依赖倒置原则的应用:
应用工厂方法之后,高层组件(也就是PizzaStore)和低层组件(也就是这些比萨)都依赖了Pizza抽象。想要遵循依赖倒置原则,工厂方法并非是唯一的技巧,但却是最有威力的技巧之一。看看上图,你将发现,低层组件现在竟然依赖高层的抽象,同样滴,高层组件现在也依赖相同的抽象。依赖的方向倒置了(从下往上?)。
避免在OO设计中违反依赖倒置原则的指导方针:
变量不可以具有具体类的引用、不要让类派生自具体类、不要覆盖基类中已实现的方法。
工厂方法模式-------定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。