设计模式-抽象工厂模式

抽象工厂模式(Abstract Factory) 提供一个创建一系列相关或相互依赖对象的接口, 而无须指定它们具体的类. 抽象工厂模式又称为Kit模式, 属于对象创建型模式.

设计模式-概述

乍一看抽象工厂模式与工厂方法模式是一样的, 它们的区别是: 工厂方法模式是对一类产品的创建的聚合, 例如: 按钮工厂, 内部包含了:圆按钮, 方按钮, 椭圆按钮等; 而抽象工厂模式是对一组的产品聚合, 例如:护眼主题工厂, 内部包含了: 绿色圆形按钮, 绿色输入框, 绿色背景等. 当一组产品有很强的关联性, 使用抽象工厂模式比工厂方法模式更方便, 结构更清晰.

结构

它包含了如下角色:

  1. AbstractFactory 抽象工厂
  2. ConcreteFactory 具体工厂
  3. AbstractProduct 抽象产品
  4. Product 具体产品

abstract-factory-1.png

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
@startuml abstract-factory-1
!include ./common.cuml

Class(AbstractFactory,"抽象工厂") << abstract >> {
+ createAbstractProduct1() : AbstractProduct1
+ createAbstractProduct2() : AbstractProduct2
+ createAbstractProductN() : AbstractProductN
}

Class(AbstractProduct1,"抽象产品1") << abstract >> {
+ use1() : void
}

Class(AbstractProduct2,"抽象产品2") << abstract >> {
+ use2() : void
}

Class(AbstractProductN,"抽象产品N") << abstract >> {
+ useN() : void
}

Class(ConcreteProduct1_1,"具体产品1-1") {
+ use1() : void
}

Class(ConcreteProduct1_2,"具体产品1-2") {
+ use1() : void
}

Class(ConcreteProduct2_1,"具体产品2-1") {
+ use2() : void
}

Class(ConcreteProduct2_2,"具体产品2-2") {
+ use2() : void
}

Class(ConcreteProductN_1,"具体产品N-1") {
+ useN() : void
}

Class(ConcreteProductN_2,"具体产品N-2") {
+ useN() : void
}

Class(ConcreteFactory1,"具体工厂1") {
+ createAbstractProduct1() : AbstractProduct1
+ createAbstractProduct2() : AbstractProduct2
+ createAbstractProductN() : AbstractProductN
}

Class(ConcreteFactory2,"具体工厂1") {
+ createAbstractProduct1() : AbstractProduct1
+ createAbstractProduct2() : AbstractProduct2
+ createAbstractProductN() : AbstractProductN
}

AbstractFactory <|..left.. ConcreteFactory1
AbstractFactory <|..right.. ConcreteFactory2

ConcreteFactory1 .down.> ConcreteProduct1_1
ConcreteFactory1 .down.> ConcreteProduct2_1
ConcreteFactory1 .down.> ConcreteProductN_1

ConcreteFactory2 .down.> ConcreteProduct1_2
ConcreteFactory2 .down.> ConcreteProduct2_2
ConcreteFactory2 .down.> ConcreteProductN_2

AbstractProduct1 <|.up.. ConcreteProduct1_1
AbstractProduct1 <|.up.. ConcreteProduct1_2
AbstractProduct2 <|.up.. ConcreteProduct2_1
AbstractProduct2 <|.up.. ConcreteProduct2_2
AbstractProductN <|.up.. ConcreteProductN_1
AbstractProductN <|.up.. ConcreteProductN_2

@enduml

使用时序

abstract-factory-2.png

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
@startuml abstract-factory-2

actor 用户 as U
entity 客户端 as C
participant 工厂A as A

U -> C : 切换主题A
activate C
C -> A : createAButton(给我一个A主题按钮)
activate C #BBBBBB
create A主题按钮 as AB
A -->> AB : 创建
C <-- A : 给你一个A主题按钮
C -> AB : 渲染A主题按钮(use)
deactivate C

C -> A : createAInput(给我一个A主题输入框)
activate C #Blue
create A主题输入框 as AI
A -->> AI : 创建
C <-- A : 给你一个A主题输入框
C -> AI : 渲染A主题输入框(use)
deactivate C

C -> A : createATable(给我一个A主题表格)
activate C #DarkSalmon
create A主题表格 as AT
A -->> AT : 创建
C <-- A : 给你一个A主题表格
C -> AT : 渲染A主题表格(use)
deactivate C
C --> U : 展示给用户看A主题

==用户觉得A主题不好看==

participant 工厂B as B
C <- U : 切换主题B
activate C
C -> B : createBButton(给我一个B主题按钮)
activate C #BBBBBB
create B主题按钮 as BB
B -->> BB : 创建
C <-- B : 给你一个B主题按钮
C -> BB : 渲染B主题按钮(use)
deactivate C

C -> B : createBInput(给我一个B主题输入框)
activate C #Blue
create B主题输入框 as BI
B -->> BI : 创建
C <-- B : 给你一个B主题输入框
C -> BI : 渲染B主题输入框(use)
deactivate C

C -> B : createBTable(给我一个B主题表格)
activate C #DarkSalmon
create B主题表格 as BT
B -->> BT : 创建
C <-- B : 给你一个B主题表格
C -> BT : 渲染B主题表格(use)
deactivate C
C --> U : 展示给用户看B主题

@enduml

代码实例

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
/**
* CreateUser: canyuda
* CreateTime: 2019/9/29 21:26
* Description:
*/
public class Main {
public static void main(String[] args) {
AbstractFactory factory = new ConcreteFactory1();
AbstractProduct1 product1 = factory.createProduct1();
AbstractProduct2 product2 = factory.createProduct2();
product1.use1();
product2.use2();
}
}

abstract class AbstractFactory {
abstract AbstractProduct1 createProduct1();

abstract AbstractProduct2 createProduct2();
}

abstract class AbstractProduct1 {
abstract void use1();
}

abstract class AbstractProduct2 {
abstract void use2();
}

class ConcreteProduct1 extends AbstractProduct1 {

@Override
void use1() {
System.out.println("使用产品1");
}
}

class ConcreteProduct2 extends AbstractProduct2 {

@Override
void use2() {
System.out.println("使用产品2");
}
}


class ConcreteFactory1 extends AbstractFactory {

@Override
AbstractProduct1 createProduct1() {
return new ConcreteProduct1();
}

@Override
AbstractProduct2 createProduct2() {
return new ConcreteProduct2();
}
}

使用场景

  • 系统不关心产品是如何创建的, 仅仅要一个产品就好了, 这个对所有的工厂模式都适用.
  • 如果各种不同种类的产品, 但是他们同属于某个分类时, 并且大多数情况下会同时使用时.

具体应用

客户端切换界面主题, 各个控件对象的构造过程都收敛到同一个工厂类中, 使用者并不关心各种控件如何构造, 并且有多个主题使用(如果仅有一个主题, 那么使用简单工厂模式就行了).