文章目录
  1. 1. 工厂方法模式概念
  2. 2. 工厂方法模式要素
  3. 3. 工厂方法模式示例

  工厂模式根据其抽象程度的逐步提高可以分为简单工厂、工厂方法模式和抽象工厂模式。关于简单工厂,可以移步我的另一篇博文设计模式——工厂模式(1):简单工厂。本文介绍第二种:工厂方法模式。
注意:本文中所提到的“接口”,并非仅指java中的interface,也包括抽象类、抽象方法等。

工厂方法模式概念

  工厂方法模式定义了一个创建产品对象的工厂接口,由子类决定要实例化的类是哪一个,它将实际创建工作推迟到子类当中。核心工厂类成为一个抽象工厂角色,仅表示具体工厂子类必须实现的接口。工厂方法模式是简单工厂基础上的进一步抽象,进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品或者是增加新的工厂。
  工厂方法模式的核心思想是:封装类中不变的部分,提取其中个性化善变的部分为独立类,通过依赖注入以达到解耦、复用和方便后期维护拓展的目的。

工厂方法模式要素

  工厂方法模式共有四个要素,如下图所示:


工厂方法模式要素

具体要素为:

  • 工厂接口Creator,它是工厂方法模式的核心。它实现了操纵产品的方法anOperation(),同时定义了一个抽象的工厂方法*factoryMethod()*,它不实现工厂方法而是留给子类去实现。
  • 具体工厂实现ConcretCreator,它实现了工厂接口的抽象的工厂方法factoryMethod(),以决定如何创造具体的产品。有多少种产品,就要有多少个具体的工厂实现。
  • 产品接口Product,它定义了产品的规范,所有产品必须实现这个共同的接口,这样一来使用这些产品的类就可以引用这个接口,而不是具体类。调用者关心的是产品接口而非具体的产品。
  • 具体产品实现ConcretProduct,它是实现产品的具体类。

工厂方法模式示例

  根据上一节中的工厂方法模式的四要素,我们假设这样一个场景:比萨类型有两个种类:纽约风味比萨芝加哥风味比萨,不同的风味下又各有四个不同原料的比萨,纽约和芝加哥两地均有比萨店的分店,需要提供以上两类的四个不同原料的比萨。让我们来看看类图:


Pizza工厂示例类图


  下面将以令纽约比萨分店NYStylePizzaStore创建纽约风味的cheese比萨NYStyleCheesePizza为例,来实现我们的工厂方法模式的demo:

  • 工厂接口:PizzaStore类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package cn.edu.whu;
/**
* 抽象工厂类
* Created by wuwenan on 10/06/2017.
*/
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);
}
  • 具体工厂实现类:NYStylePizzaStore
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package cn.edu.whu;
/**
* 具体工厂类
* Created by wuwenan on 10/06/2017.
*/
public class NYStylePizzaStore extends PizzaStore {
@Override
Pizza createPizza(String item) {
if (item.equals("cheese")) {
return new NYStyleCheesePizza();
} else if (item.equals("veggie")) {
return new NYStyleVeggiePizza();
} else if (item.equals("clam")) {
return new NYStyleClamPizza();
} else if (item.equals("pepperoni")) {
return new NYStylePepperoniPizza();
} else return null;
}
}
  • 产品接口: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
28
29
30
31
32
33
34
35
36
37
38
39
40
package cn.edu.whu;
import java.util.ArrayList;
/**
* 抽象产品类
* Created by wuwenan on 02/06/2017.
*/
public abstract class Pizza {
String name; //比萨名
String dough; //使用的面团
String sauce; //使用的酱料
ArrayList toppings = new ArrayList(); //使用的佐料
void prepare() {
System.out.println("Preparing " + name);
System.out.println("Tossing dough...");
System.out.println("Adding sauce...");
System.out.println("Adding toppings: ");
for (int i=0;i<toppings.size();i++) {
System.out.println(" " + toppings.get(i));
}
}
void bake() {
System.out.println("Baking...");
}
void cut() {
System.out.println("Cutting the pizza...");
}
void box() {
System.out.println("Placing the pizza in box...");
}
public String getName() {
return name;
}
}
  • 具体产品实现类:NYStyleCheesePizza
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package cn.edu.whu;
/**
* 具体产品类
* Created by wuwenan on 10/06/2017.
*/
public class NYStyleCheesePizza extends Pizza {
public NYStyleCheesePizza() {
name = "NY Style Cheese Pizza";
dough = "NY Style Cheese Pizza dough";
sauce = "NY Style Cheese Pizza sauce";
toppings.add("NY Style Cheese Pizza topping1");
toppings.add("NY Style Cheese Pizza topping2");
}
}
  • 测试类:PizzaTest
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package cn.edu.whu;
/**
* 测试类
* Created by wuwenan on 10/06/2017.
*/
public class PizzaTest {
public static void main(String[] args) {
PizzaStore nyPizzaStore = new NYStylePizzaStore();
String pizzaType = "cheese";
System.out.println("要创建的比萨类型是:" + pizzaType);
nyPizzaStore.orderPizza(pizzaType);
}
}

输出结果为:

1
2
3
4
5
6
7
8
9
10
要创建的比萨类型是:cheese
Preparing NY Style Cheese Pizza
Tossing dough...
Adding sauce...
Adding toppings:
NY Style Cheese Pizza topping1
NY Style Cheese Pizza topping2
Baking...
Cutting the pizza...
Placing the pizza in box...

PS:以上代码已上传至我的Github,地址是:https://github.com/Wanz2/DesignPatterns

文章目录
  1. 1. 工厂方法模式概念
  2. 2. 工厂方法模式要素
  3. 3. 工厂方法模式示例