余一

纸上得来终觉浅,绝知此事要躬行。

0%

工厂模式

1.简单工厂模式

基本介绍

  1. 简单工厂模式是属于创建型模式,是工厂模式的一种。简单工厂模式是由工厂对象决定创建出哪一种产品类的实例。
  2. 简单工厂模式:定义了一个创建对象的类,由这个类来封装实例化对象的行为(代码)
  3. 在软件开发中,当我们会用到大量创建某类,或某批对象时,就会使用到工厂模式。

示例:看一个披萨的项目:要便于披萨种类的扩展,要便于维护。

  1. 披萨的种类很多(比如GreekPizza、CheesePizza等)
  2. 披萨的制作有prepare,bake,cut,box等
  3. 完成披萨店订购功能。 传统方式:

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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
abstract class Pizza{
protected String name;

//准备原材料,每种pizza原材料不一样
public abstract void prepare();

public void bake(){
System.out.println(name + "bake");
}

public void cut(){
System.out.println(name + "cut");
}

public void box(){
System.out.println(name + "box");
}

public void setName(String name) {
this.name = name;
}
}

class CheesePizza extends Pizza{
@Override
public void prepare() {
System.out.println("准备奶酪pizza原材料");
}
}

class GreekPizza extends Pizza{
@Override
public void prepare() {
System.out.println("准备希腊pizza原材料");
}
}

class OrderPizza{

public OrderPizza() {
Pizza pizza = null;
String orderPizzaType;//订购pizza的类型
do {
orderPizzaType = getType();
if (orderPizzaType.equals("greek")){
pizza = new GreekPizza();
pizza.setName("希腊披萨");
}else if (orderPizzaType.equals("cheese")){
pizza = new CheesePizza();
pizza.setName("奶酪披萨");
} else {
break;
}
//输出pizza制作流程
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
}while (true);
}

private String getType() {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入pizza类型");
String type = scanner.next();
return type;
}
}

class PizzaStore{
public static void main(String[] args) throws ParseException {
new OrderPizza();
}
}

传统方式优缺点:

  1. 好理解,简单易操作。
  2. 缺点是违反了设计模式开闭原则,即对扩展性(提供方)开放,对(使用方)修改关闭
  3. 比如这时我们要增加一个Pizza的种类(Pepper披萨),我们要新增PepperPizza类,修改OrderPizza类的代码。

改进思路:把创建Pizza对象封装到一个类中,这样我们有了新的Pizza种类时,只需要修改类就可以,其他有创建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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
abstract class Pizza{
protected String name;

//准备原材料,每种pizza原材料不一样
public abstract void prepare();

public void bake(){
System.out.println(name + "bake");
}

public void cut(){
System.out.println(name + "cut");
}

public void box(){
System.out.println(name + "box");
}

public void setName(String name) {
this.name = name;
}
}

class CheesePizza extends Pizza{
@Override
public void prepare() {
System.out.println("准备奶酪pizza原材料");
}
}

class GreekPizza extends Pizza{
@Override
public void prepare() {
System.out.println("准备希腊pizza原材料");
}
}

class OrderPizza{
private SimpleFactory simpleFactory;
private Pizza pizza;

public OrderPizza(SimpleFactory simpleFactory) {
setSimpleFactory(simpleFactory);
}

public void setSimpleFactory(SimpleFactory simpleFactory) {
String pizzaType = "";
this.simpleFactory = simpleFactory;
do {
pizzaType = getType();
pizza = simpleFactory.createPizza(pizzaType);
if (pizzaType != null){
//输出pizza制作流程
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
}else {
System.out.println("订购pizza失败");
break;
}
}while (true);
}

private String getType() {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入pizza类型");
String type = scanner.next();
return type;
}
}

class SimpleFactory{
public Pizza createPizza(String orderPizzaType){
Pizza pizza = null;
if (orderPizzaType.equals("greek")){
pizza = new GreekPizza();
pizza.setName("希腊披萨");
}else if (orderPizzaType.equals("cheese")){
pizza = new CheesePizza();
pizza.setName("奶酪披萨");
}

return pizza;
}
}

class PizzaStore{
public static void main(String[] args) throws ParseException {
new OrderPizza();
}
}

第二种写法

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
41
class SimpleFactory{
public static Pizza createPizza(String orderPizzaType){
Pizza pizza = null;
if (orderPizzaType.equals("greek")){
pizza = new GreekPizza();
pizza.setName("希腊披萨");
}else if (orderPizzaType.equals("cheese")){
pizza = new CheesePizza();
pizza.setName("奶酪披萨");
}
return pizza;
}
}

class OrderPizza{
private Pizza pizza;
public OrderPizza() {
String pizzaType = "";
do {
pizzaType = getType();
pizza = SimpleFactory.createPizza(pizzaType);
if (pizzaType != null){
//输出pizza制作流程
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
}else {
System.out.println("订购pizza失败");
break;
}
}while (true);
}

private String getType() {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入pizza类型");
String type = scanner.next();
return type;
}
}

2.工厂方法模式

看一个新需求:

客户在点披萨时,可以点不同口味的披萨,比如北京的奶酪pizza,北京的胡椒pizza,伦敦的胡椒pizza。

思路1:

  • 使用简单工厂模式,创建不同的简单工厂类,比如BJPizzaSimpleFactory、LDPizzaSimpleFactory等等。但考虑到项目规模,以及软件的可维护性、可扩展性并不是特别好。

思路2:

  • 使用工厂方法模式

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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
abstract class Pizza{
protected String name;

//准备原材料,每种pizza原材料不一样
public abstract void prepare();

public void bake(){
System.out.println(name + "bake");
}

public void cut(){
System.out.println(name + "cut");
}

public void box(){
System.out.println(name + "box");
}

public void setName(String name) {
this.name = name;
}
}

class BJCheesePizza extends Pizza{
@Override
public void prepare() {
System.out.println("准备奶酪pizza原材料");
}
}

class BJGreekPizza extends Pizza{
@Override
public void prepare() {
System.out.println("准备BJ希腊pizza原材料");
}
}

abstract class OrderPizza{

public OrderPizza() {
Pizza pizza;
String pizzaType = "";
do {
pizzaType = getType();
pizza = createPizza(pizzaType);
if (pizzaType != null){
//输出pizza制作流程
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
}else {
System.out.println("订购pizza失败");
break;
}
}while (true);
}

protected abstract Pizza createPizza(String pizzaType);

private String getType() {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入pizza类型");
String type = scanner.next();
return type;
}
}
class BJOrderPizza extends OrderPizza{

@Override
protected Pizza createPizza(String pizzaType) {
Pizza pizza = null;
if (pizzaType.equals("greek")){
pizza = new BJGreekPizza();
}else if (pizzaType.equals("cheesePizza")){
pizza = new BJCheesePizza();
}
return pizza;
}
}

3.抽象工厂模式

基本介绍

  1. 定义了一个interface用于创建相关或有依赖关系的对象簇,而无需指明具体的类。

  2. 抽象工厂模式可以将简单工厂模式和工厂方法模式进行整合

  3. 从设计层面看,抽象工厂模式就是对简单工厂模式的改进(或称为进一步的抽象)。

  4. 将工厂抽象为两层,AbsFactory(抽象工厂)和具体实现的工厂子类。程序员可以根据创建对象类型使用对应的工厂子类。这样将简单的工厂类变成了工厂簇,更利于代码的维护和扩展。

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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
abstract class Pizza{
protected String name;

//准备原材料,每种pizza原材料不一样
public abstract void prepare();

public void bake(){
System.out.println(name + "bake");
}

public void cut(){
System.out.println(name + "cut");
}

public void box(){
System.out.println(name + "box");
}

public void setName(String name) {
this.name = name;
}
}

class BJCheesePizza extends Pizza{
@Override
public void prepare() {
System.out.println("准备奶酪pizza原材料");
}
}

class BJGreekPizza extends Pizza{
@Override
public void prepare() {
System.out.println("准备BJ希腊pizza原材料");
}
}

interface AbsFactory{
Pizza createPizza(String pizzaType);
}

class OrderPizza{
private AbsFactory absFactory;

public void setAbsFactory(AbsFactory absFactory) {
this.absFactory = absFactory;
Pizza pizza;
String pizzaType = "";
do {
pizzaType = getType();
pizza = absFactory.createPizza(pizzaType);
if (pizzaType != null){
//输出pizza制作流程
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
}else {
System.out.println("订购pizza失败");
break;
}
}while (true);
}

private String getType() {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入pizza类型");
String type = scanner.next();
return type;
}
}
class BJFactory implements AbsFactory{

@Override
public Pizza createPizza(String pizzaType) {
Pizza pizza = null;
if (pizzaType.equals("greek")){
pizza = new BJGreekPizza();
pizza.setName("BJGreekPizza");
}else if (pizzaType.equals("cheese")){
pizza = new BJCheesePizza();
pizza.setName("BJCheesePizza");
}
return pizza;
}
}

class PizzaStore{
public static void main(String[] args) throws ParseException {
OrderPizza orderPizza = new OrderPizza();
orderPizza.setAbsFactory(new BJFactory());
}
}

小结

  1. 工厂模式的意义

    将实例化对象的代码提取出来,放到一个类中统一管理和维护,达到和主项目的依赖关系的解耦。从而提高项目的扩展性和可维护性。