还是利用比萨店的例子,我们来看看一般工厂模式:
如果比萨店有许多加盟店,并且这些加盟店必须严格按照总部的要求生产比萨。
比如烘烤、切片、打包的方式。但允许加盟店根据各地的特色制作比萨。这要如何实现?
我们可以定义一个抽象类PizzaStore,这个类中有两个方法
orderPizza和createPizza,其中createPizza是抽象的。由子类来具体实现。
在orderPizza方法中定义比萨店的框架。
package com.headfirst.chapter4;
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);//工厂方法
}
纽约和芝加哥的PizzaStore继承这个抽象类
package com.headfirst.chapter4;
public class NYStylePizzaStore extends PizzaStore {
Pizza createPizza(String type) {
Pizza pizza = null;
if(type.equals("cheese")){
pizza = new NYStyleCheesePizza();
}else if(type.equals("pepperoni")){
pizza = new NYStylePepperoniPizza();
}
return pizza;
}
}
package com.headfirst.chapter4;
public class ChicagoStylePizzaStore extends PizzaStore{
Pizza createPizza(String type) {
Pizza pizza = null;
if(type.equals("cheese")){
pizza = new ChicagoStyleCheesePizza();
}else if(type.equals("pepperoni")){
pizza = new ChicagoStylePepperoniPizza();
}
return pizza;
}
}
在这两个子类中依据传入参数的类型来决定具体需要生产的比萨。
同样:Pizza类也定义为抽象的
package com.headfirst.chapter4;
import java.util.ArrayList;
import java.util.List;
public abstract class Pizza {
String name;
String dough;
String sauce;
List topping = new ArrayList();
void prepare(){
System.out.println("Preparing "+name);
System.out.println("Tossing dough...");
System.out.println("Adding sauce...");
for (int i = 0; i < topping.size(); i++) {
System.out.println(""+topping.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 offical PizzaStore box");
System.out.println();
}
public String getName(){
return name;
}
}
以下为各城市加盟店具体生产的比萨
package com.headfirst.chapter4;
public class NYStyleCheesePizza extends Pizza {
public NYStyleCheesePizza() {
name = "NY Style Sauce and Cheese Pizza";
dough = "Thin Crust Dough";
sauce = "Marinara Sauce";
topping.add("Grated Reggiano Cheese");
}
}
package com.headfirst.chapter4;
public class NYStylePepperoniPizza extends Pizza {
public NYStylePepperoniPizza() {
name = "NY Styel Pepperon Pizza";
dough ="NY Styel pepperon dough";
sauce = "pepperon sauce";
topping.add("pepperon topping");
}
}
package com.headfirst.chapter4;
public class ChicagoStyleCheesePizza extends Pizza{
public ChicagoStyleCheesePizza() {
name = "Chicago Style Deep Dish Cheese Pizza";
dough = "Extra Thick Crust Dough";
sauce = "Plum Tomato Sauce";
topping.add("Shredded Mozzarella Cheese");
}
void cut() {
System.out.println("Cutting the pizza into square slice");
}
}
package com.headfirst.chapter4;
public class ChicagoStylePepperoniPizza extends Pizza {
public ChicagoStylePepperoniPizza() {
name = "Chicago Style Pepperoni Pizza";
dough = "Chicago Style Pepperoni dough";
sauce = "Chicago Style Pepperoni sauce";
topping.add("Chicago Style topping");
}
}
最后写一个测试类:
package com.headfirst.chapter4;
public class PizzaTestDrive {
public static void main(String[] args) {
PizzaStore nyPizzaStore = new NYStylePizzaStore();
PizzaStore chicagoPizzaStore = new ChicagoStylePizzaStore();
nyPizzaStore.orderPizza("cheese");
chicagoPizzaStore.orderPizza("cheese");
}
}
所有的工厂模式都用来封闭对象的创建,工厂方法模式通过让子类决定该创建的对象是什么,来达到将对象创建的过程封闭的目的。
定义工厂方法模式:
工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的是哪一个。工厂方法让类把实例化推迟到子类。
上图中的Creator是一个类,它实现了所有操纵产品的方法 ,但不实现工厂方法
Creator所有的子类都必须实现这个抽象的factoryMethod()方法。
ConcreteCreator实现了factoryMethod()方法以制造实现产品。
简单工厂与工厂方法的差异:
简单工厂把全部的事情在一个地方都处理完了,而工厂方法却是创建一个框架,让子类决定要如何实现。
使用工厂方法有什么好处?
1,避免代码重复
2,方便后期维护
3,针对接口编程,使代码更有弹性,方便未来扩展。