设计模式--结构型:组合模式

组合模式:将对象组合成树形结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性

组合模式 Composite :通常用于可以使用树状结构描述的场景,比如:

  • 公司的组织结构图
    公司包含多个部门:行政部,研发部,生产部,以及多个子公司,每个子公司又会有各自的行政部,研发部等,典型的树状结构。
  • 操作系统中的文件系统
    文件系统包含:文件和文件夹,每个文件夹目录下又可以包含多个子目录及文件。
  • 常见的 UI 框架
    比如 AndroidUI 框架中:ViewViewGroup 的关系。View 为叶子节点,ViewGroup 为容器,可以包含 View 以及子 ViewGroup

组合模式有两种结构:

  • 安全组合模式
  • 透明组合模式

安全组合模式

类图结构

0054-Composite_typesafety-uml-classdiag.png

结构解析

  • Component
    抽象类,定义组合模式中对象的公共接口。
  • Leaf
    叶子节点,实现组合模式中的抽象方法。
  • Composite
    枝干节点,包含多个叶子节点。

示例

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
// 1. Component
public abstract class Component {
public abstract void operation();
}

// 2. Leaf
public class Leaf extends Component{
@Override
public void operation() {
System.out.println("Leaf::operation.");
}
}

// 3. Composite
public class Composite extends Component{
private List<Component> componentList = new ArrayList<>();

public void add(Component component){
componentList.add(component);
}

public void remove(Component component){
componentList.remove(component);
}

public Component getChild(int index){
return componentList.get(index);
}

@Override
public void operation() {
System.out.println("Composite::operation.");
for (Component component : componentList){
component.operation();
}
}
}

// 4. Test
public class TestCompositeTypeSafety {
public static void main(String[] args) {
Composite branch = new Composite();
Leaf branch_leaf1 = new Leaf();
Leaf branch_leaf2 = new Leaf();
branch.add(branch_leaf1);
branch.add(branch_leaf2);

Composite root = new Composite();
Leaf leaf = new Leaf();
root.add(leaf);
root.add(branch);

root.operation();
}
}

// 5. Result
Composite::operation.
Leaf::operation.
Composite::operation.
Leaf::operation.
Leaf::operation.

透明组合模式

类图结构

0054-Composite_uniformity-uml-classdiag.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
77
78
79
80
81
82
83
// 1. Component
public abstract class Component {
public abstract void add(Component component);
public abstract void remove(Component component);
public abstract Component getChild(int index);
public abstract void operation();
}

// 2. Leaf
public class Leaf extends Component{
@Override
public void add(Component component) {
throw new UnsupportedOperationException("Cannot add to a leaf.");
}

@Override
public void remove(Component component) {
throw new UnsupportedOperationException("Cannot remove from a leaf.");
}

@Override
public Component getChild(int index) {
throw new UnsupportedOperationException("Cannot getchildfrom a leaf.");
}

@Override
public void operation() {
System.out.println("Leaf::operation.");
}
}

// 3. Composite
public class Composite extends Component{
private List<Component> componentList = new ArrayList<>();

@Override
public void add(Component component) {
componentList.add(component);
}

@Override
public void remove(Component component) {
componentList.remove(component);
}

@Override
public Component getChild(int index) {
return componentList.get(index);
}

@Override
public void operation() {
System.out.println("Composite::operation.");
for (Component component : componentList){
component.operation();
}
}
}

// 4. Test
public class TestCompositeUniformity {
public static void main(String[] args) {
Component branch = new Composite();
Component branch_leaf1 = new Leaf();
Component branch_leaf2 = new Leaf();
branch.add(branch_leaf1);
branch.add(branch_leaf2);

Component root = new Composite();
Component leaf = new Leaf();
root.add(leaf);
root.add(branch);

root.operation();
}
}

// 5. Result
Composite::operation.
Leaf::operation.
Composite::operation.
Leaf::operation.
Leaf::operation.

总结

从两种组合模式的类图结构和示例中,可以看出他们最大的不同在与 Component

  • 安全组合模式
    Component 中并没有将管理子对象抽象出来,也就是不包含 add/remove 等,但是这会导致子对象和组合对象接口不一致。Android View/ViewGroup 就属于安全组合模式。
  • 透明组合模式
    Component 中将管理子对象抽象到基类中,使得子对象和组合对象具有完全一致的行为接口,但是叶子类实际上并不需要这些管理行为。

优缺点:

  • 优点
    组合模式可以清楚的定义分层次的复杂对象,高层模块可以忽略层次的差异,调用简单。增加叶子或者树干,不需要修改类库,在客户端就可以实现,符合开闭原则。
  • 缺点
    组合模式的叶子节点和组合类都是实现类,违反了依赖倒置原则。

参考文档

  • 大话设计模式
  • Android 源码设计模式解析与实战
0%