喵星之旅-沉睡的猫咪-组合模式

一、组合模式是什么

组合模式也称为整体-部分模式,它的宗旨是通过将单个对象和组合对象用相同的接口进行表示,使得客户对单个对象和组合对象的使用具有一致性,属于结构型模式。

最常见的就是树结构的实现,比如红黑树。

这个给我的感觉更像是一种分形的特点,从任何一点去看,貌似都是一样的,这里指的是他的方法、属性等。从部分可以看出整体的结构。

二、组合模式的实现

下面通过实例演示一个组合模式如果来做,就是一个多叉树的实现。

第一步:问题必须要数型结构。比如我们的目录。如果是区分叶子和树枝的,要求分别创建不同的实现类,如果不区分,那就一个类直接实现,不需要抽象组件。

这里我们考虑是一个可以无限扩展的数,所以不区分。

第二步:明确每个节点的功能:一般是存储哪些数据、如何显示数据、子节点的操作、也不排除出现父节点的操作,还有其他的一些常用功能,比如遍历。

这里选择数据结点不会随便变化,不像红黑树那样复杂,是数据一确定就基本不改变,只有删除和添加的功能。

最后确定属性:子节点(如果数据量确定,就挨个列出(比如二叉树),不确定就用列表)这里选择list。存值value。目录级别(红黑树中应该没有,这里结构基本没变化,只要数据添加就是那个级别,其他数据不会影响这个数据)。

方法:添加节点、删除节点、遍历、属性的对应getset方法、构造器。

第三步:针对特别的场景,添加、或者修改一些方法、属性。

三、代码示例

节点类

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
package structure.composite;

import java.util.ArrayList;
import java.util.List;
/**
*
* @author bunny~~我是兔子我会喵,我叫喵星兔。
*直接new的节点不能作为根结点,也不能直接遍历。
*必须通过静态方法才能创建根结点。
*这个要求不是必须的,只是这里选择这样做。
*/

public class Node {
//子节点
private List<Node> children;
//存储数据
private String value;
//目录层级
private Integer level;
public List<Node> getChildren() {
return children;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public int getLevel() {
return level;
}
private void setLevel(Integer level) {
this.level = level;
}
//处理子节点层级
private void setChildrenLevel() {
for (int i = 0; i < children.size(); i++) {
Node n = children.get(i);
n.setLevel(level + 1);
n.setChildrenLevel();
}
}
//遍历
public void show() {
if (level == null) {
System.out.println("不是正常结点");
return;
}
String s = "";
for (int i = 0; i < level; i++) {
s += " ";
}
System.out.println(s + (children.size() > 0 ? "+" : "") + value);
for (int i = 0; i < children.size(); i++) {
children.get(i).show();
}
}
//添加节点,需要考虑层级
public void addNode(Node node) {
children.add(node);
node.setLevel(level + 1);
node.setChildrenLevel();
}
//删除节点
public void remove(Node node) {
children.remove(node);
}
public Node() {
children = new ArrayList<Node>();
}

public Node(String value) {
super();
this.value = value;
children = new ArrayList<Node>();
}
public static Node newRoot() {
Node node = new Node();
node.setLevel(0);
return node;
}
public static Node newRoot(String value) {
Node node = new Node(value);
node.setLevel(0);
return node;
}
}

测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package structure.composite;

public class Test {

public static void main(String[] args) {
Node n1 = new Node("a");
Node n2 = new Node("as");
Node n3 = new Node("ad");
Node n4 = new Node("af");
Node n5 = new Node("ag");
Node n6 = new Node("ah");
Node r = Node.newRoot("root");
r.addNode(n6);
r.addNode(n4);
n4.addNode(n2);
n2.addNode(n1);
n4.addNode(n3);
r.show();
}

}

四、组合模式分类

组合模式的结构:

抽象构件(Component)角色:它的主要作用是为树叶构件和树枝构件声明公共接口,并实现它们的默认行为。在透明式的组合模式中抽象构件还声明访问和管理子类的接口;在安全式的组合模式中不声明访问和管理子类的接口,管理工作由树枝构件完成。

树叶构件(Leaf)角色:是组合中的叶节点对象,它没有子节点,用于实现抽象构件角色中 声明的公共接口。

树枝构件(Composite)角色:是组合中的分支节点对象,它有子节点。它实现了抽象构件角色中声明的接口,它的主要作用是存储和管理子部件,通常包含 Add()、Remove()、GetChild() 等方法。

如何分类:

这种设计模式具体还分成两类:透明的、安全的。

如果需要区分树枝和树叶,那么上面的例子需要变成2个不同的对象,分别对树枝和树叶采取不同的处理。然后上面抽象出统一的接口。

接口的内容决定是透明的还是安全的组合模式。

所谓安全的组合模式,是调用方法时不会出现未实现的情况,所以接口内容较少,当要使用具体类型特有的功能时,需要知道具体类型。透明的在接口中有所有的方法,但是可能时空实现。

文章目录
  1. 一、组合模式是什么
  2. 二、组合模式的实现
  3. 三、代码示例
  4. 四、组合模式分类
|