在http://quicker.iteye.com/blog/571714一文中已经讲了简单工厂和工厂方法并且有UML图和实现的代码。
这里只结合实例分析一下工厂方法在实际生活中的应用。
我们看看比萨店及比萨的图。
产品图。
结合http://quicker.iteye.com/blog/571714中关于工厂方法模式的实现,不难得出实现代码:
package com.lwf.disign.learn.factorymethod;
public abstract class PizzaStore {
public final Pizza orderPizza(String type){
Pizza pizza;
pizza = createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
abstract Pizza createPizza(String type);
}
package com.lwf.disign.learn.factorymethod;
public class NYPizzaStore extends PizzaStore {
Pizza createPizza(String type) {
Pizza pizza = null;
if(type.equals("cheese")){
pizza = new NYCheesePizza();
}else if(type.equals("veggle")){
pizza = new NYVegglePizza();
}
return pizza;
}
}
package com.lwf.disign.learn.factorymethod;
public class ChicagoPizzaStore extends PizzaStore {
Pizza createPizza(String type) {
Pizza pizza = null;
if(type.equals("cheese")){
pizza = new ChicagoCheesePizza();
}else if(type.equals("veggle")){
pizza = new ChicagoVegglePizza();
}
return pizza;
}
}
package com.lwf.disign.learn.factorymethod;
import java.util.ArrayList;
public abstract class Pizza {
String name; //名称
String dough; //面团类型
String sauce; //酱料类型
ArrayList toppings = new ArrayList(); //一套佐料
public void prepare() {
System.out.println("Preparing " + name);
System.out.println("Tossign dough..." + dough);
System.out.println("Adding sauce..." + sauce);
System.out.println("Adding toppings: ");
for (int i = 0; i < toppings.size(); i++) {
System.out.println(" " + toppings.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("Pizza in offical PizzaStrore box");
}
public String getName(){
return name;
}
}
package com.lwf.disign.learn.factorymethod;
public class NYCheesePizza extends Pizza {
public NYCheesePizza(){
name = "NYCheesePizza";
dough = "Thin crust dough NYCheesePizza";
sauce = "Marina sauce NYCheesePizza";
toppings.add("Grated NYCheesePizza cheese");
}
public void cut(){
System.out.println("cut it into NYCheesePizza slices");
}
}
package com.lwf.disign.learn.factorymethod;
public class NYVegglePizza extends Pizza {
public NYVegglePizza(){
name = "NYVegglePizza";
dough = "Thin crust dough NYVegglePizza";
sauce = "Marina sauce NYVegglePizza";
toppings.add("Grated NYVegglePizza cheese");
}
public void cut(){
System.out.println("cut it into NYVegglePizza slices");
}
}
package com.lwf.disign.learn.factorymethod;
public class ChicagoCheesePizza extends Pizza {
public ChicagoCheesePizza(){
name = "ChicagoCheesePizza";
dough = "Thin crust dough ChicagoCheesePizza";
sauce = "Marina sauce ChicagoCheesePizza";
toppings.add("Grated ChicagoCheesePizza cheese");
}
public void cut(){
System.out.println("cut it into ChicagoCheesePizza slices");
}
}
package com.lwf.disign.learn.factorymethod;
public class ChicagoVegglePizza extends Pizza {
public ChicagoVegglePizza(){
name = "ChicagoVegglePizza";
dough = "Thin crust dough ChicagoVegglePizza";
sauce = "Marina sauce ChicagoVegglePizza";
toppings.add("Grated ChicagoVegglePizza cheese");
}
public void cut(){
System.out.println("cut it into ChicagoVegglePizza slices");
}
}
上面共定义了四种比萨,客户向系统订购这四种比萨。。
package com.lwf.disign.learn.factorymethod;
public class PizzaStoreTest {
public static void main(String[] args) {
PizzaStore pizzaStore = new NYPizzaStore();
Pizza pizza = pizzaStore.orderPizza("cheese");
print(pizza.getName());
pizza = pizzaStore.orderPizza("veggle");
print(pizza.getName());
pizzaStore = new ChicagoPizzaStore();
pizza = pizzaStore.orderPizza("cheese");
print(pizza.getName());
pizza = pizzaStore.orderPizza("veggle");
print(pizza.getName());
}
public static void print(String name){
System.out.println(name);
System.out.println("-------------------------------------------------------------");
}
}
输出结果为:
Preparing NYCheesePizza
Tossign dough...Thin crust dough NYCheesePizza
Adding sauce...Marina sauce NYCheesePizza
Adding toppings:
Grated NYCheesePizza cheese
Bake for 25 minutes at 350
cut it into NYCheesePizza slices
Pizza in offical PizzaStrore box
NYCheesePizza
-------------------------------------------------------------
Preparing NYVegglePizza
Tossign dough...Thin crust dough NYVegglePizza
Adding sauce...Marina sauce NYVegglePizza
Adding toppings:
Grated NYVegglePizza cheese
Bake for 25 minutes at 350
cut it into NYVegglePizza slices
Pizza in offical PizzaStrore box
NYVegglePizza
-------------------------------------------------------------
Preparing ChicagoCheesePizza
Tossign dough...Thin crust dough ChicagoCheesePizza
Adding sauce...Marina sauce ChicagoCheesePizza
Adding toppings:
Grated ChicagoCheesePizza cheese
Bake for 25 minutes at 350
cut it into ChicagoCheesePizza slices
Pizza in offical PizzaStrore box
ChicagoCheesePizza
-------------------------------------------------------------
Preparing ChicagoVegglePizza
Tossign dough...Thin crust dough ChicagoVegglePizza
Adding sauce...Marina sauce ChicagoVegglePizza
Adding toppings:
Grated ChicagoVegglePizza cheese
Bake for 25 minutes at 350
cut it into ChicagoVegglePizza slices
Pizza in offical PizzaStrore box
ChicagoVegglePizza
-------------------------------------------------------------
设计原则:要依赖抽象,不要依赖具体类,也叫依赖倒置原则
如下图:
可以看到上下都依赖于pizza这个抽象类..
这启发我们思考方式的变化,我们也可以倒置思考方式:如一般你想开个比萨店先会想到要用什么做比萨,考虑一大堆原料等。。。最后才是比萨店。那么我们可以改变思考的方式,我们只需要把比萨先做一个抽象。那们上我们可以开比萨店,下我们可以制作多种类型的比萨。
下面有几种方式可以让我们尽可能的遵守倒置原则
然而上面的三点要求对待程序可谓是严格的。。当然如果一个类以后变化的机会很少,那么为什么不直接new出来呢。如String类。。所以这些都只是让我们的设计变得更好的方针,不能死套在程序上。