1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
public
Pizza orderPizza(String type) {
Pizza pizza;
//-------------------------------------------------------------
//---------------------将虚线下代码提取出来--------------------
if
(type.equals(
"cheese"
))
pizza =
new
CheesePizza();
else
if
(type.equals(
"greek"
))
pizza =
new
GreekPizza();
else
if
(type.equals(
"pepperoni"
))
pizza =
new
PepperoniPizza();
//--------------------将虚线上代码提取出来----------------------
//--------------------------------------------------------------
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return
pizza;
}
|
这里有一些要实例化的具体类,究竟实例化哪个类,要在运行时由一些条件来决定。当看到这样的代码,一旦有变化或扩展,就必须重新打开这段代码进行检查和修改。通常这样修改过的代码将造成部分系统给更难维护和更新,而且也更容易犯错。应当找出变化的方面,把它们从不变的部分分离出来。别忘了,我们应当面向接口编程,代码改变如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
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);
}
|
由工厂专门来处理创建对象的细节,一旦有了工厂,orderPizza()就变成此对象的客户。orderPizza只关心从工厂得到一个比萨。
建立一个简单的工厂,为所有比萨封装创建对象的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
public
class
PizzaFactory
extends
PizzaStore {
public
Pizza createPizza(String type) {
// TODO Auto-generated method stub
Pizza pizza;
if
(type.equals(
"cheese"
)) {
pizza =
new
CheesePizza();
}
else
if
(type.equals(
"greek"
)) {
pizza =
new
GreekPizza();
}
else
if
(type.equals(
"pepperoni"
)) {
pizza =
new
PepperoniPizza();
}
return
pizza;
}
}
|
这样做有什么好处?似乎只是把问题搬到另一个对象罢了。别忘了,PizzaFactory可有许多客户,可能还有PizzaShopMenu(比萨店菜单),HomeDelivery(宅急送)类,会利用这个工厂来取得比萨。把创建对象的代码封装到一个类,当以后实现改变时,只需修改这个类即可。我们正是把具体实例化的过程,从客户的代码中删除,让PizzaStore的各个子类负责定义自己的createPizza()方法。
abstract product factoryMethod(String type)
在上例中createPizza就是一个工厂方法。工厂方法是抽象的,所以依赖子类来处理对象的创建;工厂方法必须返回一个产品,超类中定义的方法,通常使用到工厂方法的返回值;工厂方法用来处理对象的创建,并将这样的行为封装在子类中,这样客户程序中关于超类的代码就和子类对象创建代码解耦了。
本文转自 ponpon_ 51CTO博客,原文链接:http://blog.51cto.com/liuxp0827/1353209,如需转载请自行联系原作者