人的知识就好比一个圆圈,圆圈里面是已知的,圆圈外面是未知的。你知道得越多,圆圈也就越大,你不知道的也就越多。

0%

设计模式--组合模式

定义

组合模式允许你将对象组合成树形结构来表现“整体/部分”层次结构。组合能让客户以一致的方式处理个别对象以及对象组合。

角色

  • 抽象构件(Component):其主要作用是为树枝构件和树叶构件声明公共接口,并实现它们的默认行为。在透明式的组合模式中,抽象构件还声明访问和管理子类的接口;在安全式的组合模式中,不声明访问和管理子类的接口,管理工作由树枝构件完成。
  • 树枝构件(Composite):是组合中的分支节点对象,它有子节点。它实现了抽象构件角色中声明的接口,它的主要作用是存储和管理子部件。
  • 树叶构件(Leaf):是组合中的叶节点对象,它没有子节点,用于实现抽象构件角色中声明的公共接口。

类图

Composite UML

实现

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
/**
* 抽象构件接口
*/
public interface Component {

/**
* 操作
*/
void operation();

/**
* 添加子节点
*
* @param component 构件
*/
default void add(Component component) {
throw new UnsupportedOperationException();
}

/**
* 移除子节点
*
* @param component 构件
*/
default void remove(Component component){
throw new UnsupportedOperationException();
}

/**
* 获取第index个子节点
*
* @param index 下标
*/
default Component getChild(int index){
throw new UnsupportedOperationException();
}
}

/**
* 树叶节点
*/
public class Leaf implements Component {

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

/**
* 树枝节点
*/
public class Composite implements Component {
private List<Component> children = new ArrayList<>();

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

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

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

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

优缺点

优点

  • 组合模式使得客户端代码可以一致的处理对象和对象容器,无需关心处理的是单个对象,还是组合的对象容器
  • 将客户对象与复杂的对象容器结构解耦
  • 可以更容易地往组合对象中加入新的构件

缺点

  • 使得设计更加复杂,客户端需要花更多时间理清类之间的层次关系

适用场景

  • 当想表达对象的部分-整体的层次结构时
  • 希望用户忽略组合对象与单个对象不同,用户将统一地使用组合结构中的所有对象时

模式应用

Mybatis

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public interface SqlNode {
boolean apply(DynamicContext context);
}

public class MixedSqlNode implements SqlNode {
private final List<SqlNode> contents;

public MixedSqlNode(List<SqlNode> contents) {
this.contents = contents;
}

@Override
public boolean apply(DynamicContext context) {
for (SqlNode sqlNode : contents) {
sqlNode.apply(context);
}
return true;
}
}

识别组合模式的一个要点:实现了一个接口,又聚合了这个接口的集合,那么该类很有可能是组合模式中的组合对象。

小礼物走一走,来 Github 关注我