一、工厂方法
定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
二、设计原则
要依赖抽象,不要依赖具体
这个原则说明了:不能让高层组件依赖低层组件,而且,不管高层或低层组件,“两者”都应该依赖于抽象
PoizzaStore是“高层组件”,披萨实现是“低层组件”,很清楚地,PizzaStore依赖这些具体披萨类Pizza。
三、代码实现
1、披萨类--产品类
package com.oyhp.pizza;
//披萨类--产品类
import java.util.ArrayList;
public abstract class Pizza {
String name; //名称
String dough; //面团类型
String sauce; //酱料类型
ArrayList<String> toping = new ArrayList<>(); //佐料
public void prepare(){
System.out.println("Prepare " + name);
System.out.println("Tossing dough...");
System.out.println("Adding sauce...");
System.out.println("Adding topping:");
for(int i = 0; i < toping.size(); i++){
System.out.println(" " + toping.get(i));
}
}
public void bake(){
System.out.println("Bake for 25 minutes at 350");
}
public void cut(){
System.out.println("Cutting the pizza into diagonal slices");
}
public void box(){
System.out.println("Place pizza in official PizzaStore box");
}
public String getName(){
return name;
}
}
package com.oyhp.pizza;
//纽约风格披萨--具体产品类
public class NYStryleCheesePizza extends Pizza{
public NYStryleCheesePizza() {
// TODO Auto-generated constructor stub
name = "NY Style Sauce and Cheese Pizza";
dough = "Thin Crust Dough";
sauce = "Marinara Sauce";
toping.add("Grated Reggiano Cheese");
}
}
package com.oyhp.pizza;
//芝加哥风格披萨--具体产品类
public class ChicagoStyleCheesePizza extends Pizza{
public ChicagoStyleCheesePizza() {
// TODO Auto-generated constructor stub
name = "Chicago Style Sauce and Cheese Pizza";
dough = "Extra Thin Crust Dough";
sauce = "Plum Tomato Sauce";
toping.add("Sredded Mozzarella Cheese");
}
@Override
public void cut() {
// TODO Auto-generated method stub
System.out.println("Cutting the pizza into squre slices");
}
}
2、披萨商店--创建类
package com.oyhp.pizzastore;
import com.oyhp.pizza.Pizza;
//披萨商店--创建类
public abstract class PizzaStore {
public Pizza orderPizza(String type){
Pizza pizza;
//创建披萨
pizza = createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
protected abstract Pizza createPizza(String type);
}
package com.oyhp.pizzastore;
import com.oyhp.pizza.NYStryleCheesePizza;
import com.oyhp.pizza.Pizza;
//纽约风格披萨店--具体创造类
public class NYStylePizzaStore extends PizzaStore{
Pizza pizza;
@Override
protected Pizza createPizza(String type) {
// TODO Auto-generated method stub
if(type.equals("cheese")){
pizza = new NYStryleCheesePizza();
}else if(type.equals("pepperoni")){
pizza = new NYStryleCheesePizza();
}
return pizza;
}
}
package com.oyhp.pizzastore;
import com.oyhp.pizza.ChicagoStyleCheesePizza;
import com.oyhp.pizza.NYStryleCheesePizza;
import com.oyhp.pizza.Pizza;
//芝加哥风格披萨店--具体创造类
public class ChicagoStylePizzaStore extends PizzaStore{
Pizza pizza;
@Override
protected Pizza createPizza(String type) {
// TODO Auto-generated method stub
if(type.equals("cheese")){
pizza = new ChicagoStyleCheesePizza();
}else if(type.equals("pepperoni")){
pizza = new ChicagoStyleCheesePizza();
}
return pizza;
}
}
3、main
package com.oyhp.main;
import com.oyhp.pizza.Pizza;
import com.oyhp.pizzastore.ChicagoStylePizzaStore;
import com.oyhp.pizzastore.NYStylePizzaStore;
import com.oyhp.pizzastore.PizzaStore;
//所有工厂模式都用来封装对象的创建。工厂方法模式通过让子类决定改创建的对象是什么,来达到将对象创建的过程封装的目的。
/*
* 平行的类层级
* 产品类与创建类是平行的,因为他们都有抽象类,而抽象类都有许多具体的子类,
* 每个子类都有自己特定的实现,通过orderPizza()方法和一个工厂方法联合起来
*/
public class DoRun {
public static void main(String[] args) {
PizzaStore nyStore = new NYStylePizzaStore();
PizzaStore chicagoStore = new ChicagoStylePizzaStore();
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");
}
}
四、类图
五、总结
1、所有的工厂都是用来封装对象的创建
2、工厂方法使用继承:把对象的创建委托给子类,让子类实现工厂方法来创建对象
3、所有工厂模式都通过减少应用程序和具体类之间的依赖促进松耦合
4、依赖导致原则,知道我们避免依赖具体类型,而要尽量依赖抽象
5、工厂是很有威力的技巧,帮助我们针对抽象编程,而不要针对具体类编程