Technology-设计模式-工厂模式

本文介绍了GoF中的工厂模式。

模式推演

创造不同类型的披萨:

初始写法为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class PizzaStore{
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;
}
}

显然,如果要加入一种新的pizza,就得修改这个方法,并且下方的prepare这些方法是不变的。我们必须封装变化。

创建简单工厂:

从需求来看,创建pizza是变化部分,我们将其从原来的类中独立出来,用一个专门的类来负责创造:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class SimpleFactrory{

Pizza createPizza(String type){
Pizza pizza = null;

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;
}

}

简单工厂其实不是一种设计模式,而像是一种编程习惯。

工厂方法

每个地方的pizza口味不一样,例如深圳和广州两地的,用简单工厂方法,不能满足这种扩展需求,因此我们进一步优化,把createPizza方法通过抽象类的方式,让子类来决定:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class abstract PizzaStore{

Pizza orderPizza(String type){
Pizza pizza = createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}

abstract Pizza createPizza(String type);
}


class SZPizzaStore extends PizzaStore{

Pizza createPizza(String type){
Pizza pizza = null;

if(type.equals("cheese"))
pizza = new SZCheesePizza();
else if(type.equals("greek"))
pizza = new SZGreekPizza();
else if(type.equals("pepperoni"))
pizza = new SZPepperoniPizza();
return pizza;
}
}

工厂方法与简单工厂的不同是:简单工厂把全部事情,在一个地方都处理了,而工厂方法是创建一个框架,让子类决定如何实现。简单工厂不涉及到继承,只是一个简单的类,而工厂方法可以利用继承具备弹性。

依赖倒置

如果没有使用工厂方法,写法是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class PizzaStore{
Pizza orderPizza(String style, String type){
Pizza pizza = null;

if(style.equals("NY")){
if(type.equals("cheese"))
pizza = new NYCheesePizza();
else if(type.equals("greek"))
pizza = new NYGreekPizza();
else if(type.equals("pepperoni"))
pizza = new NYPepperoniPizza();
}else if(style.equals("Chicago")){
if(type.equals("cheese"))
pizza = new ChicagoCheesePizza();
else if(type.equals("greek"))
pizza = new ChicagoGreekPizza();
else if(type.equals("pepperoni"))
pizza = new ChicagoPepperoniPizza();
}

pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
}

依赖关系如下:

Technology-DesignPattern-Factory-Dependency

如果设计一个Pizza的基类,PizzaStore只依赖于Pizza类,那么依赖关系如下:

Technology-DesignPattern-Factory-DependencyInversion

可见,依赖关系从上往下,变成从下往上了,即底层的组件反向依赖高层的抽象。

OO原则(依赖倒置原则):要依赖抽象,不要依赖具体类。

当工厂创造的产品种类不止一种且可能重复时

Pizza需要一些原料,例如sauce、cheese、clam,这些原料对于多种Pizza可能相同,所以我们需要通过工厂来生成这些原料,但也可能不同,所以我们需要定义多个工厂,把工厂的共有方法通过抽象提取出来:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public interface PizzaIngredientFactroy{
public Sauce createSacce();
public Cheese createCheese();
public Clam createClam();
}

public class NYPizzaIngredientFactroy implements PizzaIngredientFactroy{
...
}

public class ChigagoPizzaIngredientFactroy implements PizzaIngredientFactroy{
...
}

public class Pizza{
private PizzaIngredientFactroy factroy;
}

这种设计模式,就是抽象工厂模式,抽象工厂与工厂方法不同,工厂方法是通过继承的方式,只创造一种产品,而抽象工厂是通过组合,创造一个产品家族。

定义

工厂方法模式(Factory Pattern):定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个,工厂方法让类把实例化推迟到子类。

类图:

Technology-DesignPattern-Factory-Class

抽象工厂模式:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。

类图:

Technology-DesignPattern-AbstractFactory-Class