1. 组合模式简介
组合模式(Composite Pattern)是结构性设计模式,又叫“部分-整体”模式,主要用于树形结构的处理。父节点是整体,子节点是父节点的部分,它们具有相似的行为。
组合模式的角色一共有三种。
Leaf(叶节点角色): 叶子节点,即没有字节点的节点,本模式中的“部分”角色,例如文件系统中文件。
Composite(枝节点角色):枝节点,即本模式中的“整体”角色,它包含子节点,字节点既可以是枝节点,也可以是叶节点;例如文件系统中的文件夹。
Component(抽象组件角色): 是组合模式中Composite和Leaf共同的父接口(抽象类),在此接口中声明所有子类的共有的方法。
2. 组合模式举例
公司有部门和员工,可以形成一个树形结构,如果有一份通知要下发个全部的部门,或者某个事业部,需要选中对应的节点,即可完成对该节点所有子节点的通知。
序号 | 类名 | 角色 | 说明 |
---|---|---|---|
1 | Node | Component | 抽象组件角色,抽象节点 |
2 | Staff | Leaf | 叶节点角色,员工 |
3 | OrgNode | Composite | 枝节点角色,部门(公司、事业部) |
4 | CompisteMain | 客户端 | 演示调用,通知发布 |
1. Node类
// 抽象组件,抽象的组织结构节点
public interface Node {
// 增加子节点
void add(Node node);
// 移除子节点
void remove(Node node);
// 获取第i个子节点
Node get(int i);
// 发布通知
void inform(String information);
}
2. Staff类
// 叶节没有子节点,因此它实现的add、remove等方法抛出异常。
public class Staff implements Node {
private String name;
public Staff(String name) {
this.name = name;
}
@Override
public void add(Node node) {
throw new UnsupportedOperationException();
}
@Override
public void remove(Node node) {
throw new UnsupportedOperationException();
}
@Override
public Node get(int i) {
throw new UnsupportedOperationException();
}
@Override
public void inform(String information) {
System.out.println("员工 [" + name + "] 收到通知:" + information);
}
}
3. OrgNode
// 枝节点角色
public class OrgNode implements Node {
private String name;
private List<Node> nodeList = new ArrayList<>();
public OrgNode(String name) {
this.name = name;
}
@Override
public void add(Node node) {
nodeList.add(node);
}
@Override
public void remove(Node node) {
nodeList.remove(node);
}
@Override
public Node get(int i) {
Node node = null;
if (i >= 0 && i < nodeList.size()) {
node = nodeList.get(i);
}
return node;
}
// 递归调用
@Override
public void inform(String information) {
System.out.println("机构 [" + name + "] 收到通知:" + information);
for (Node node : nodeList) {
node.inform(information);
}
}
}
4. CompositeMain
public class CompisteMain {
public static void main(String[] args) {
Node com = new OrgNode("公司");
Node market = new OrgNode("市场部");
Node rd = new OrgNode("研发部");
Node ceo = new Staff("ceo 王");
com.add(market);
com.add(rd);
com.add(ceo);
Node steve = new Staff("史蒂夫");
market.add(steve);
Node james = new Staff("詹姆斯");
Node vince = new Staff("文斯");
rd.add(james);
rd.add(vince);
String infomation = " 1 + 1 = 2 ";
com.inform(infomation);
}
}
输出结果:
机构 [公司] 收到通知: 1 + 1 = 2
机构 [市场部] 收到通知: 1 + 1 = 2
员工 [史蒂夫] 收到通知: 1 + 1 = 2
机构 [研发部] 收到通知: 1 + 1 = 2
员工 [詹姆斯] 收到通知: 1 + 1 = 2
员工 [文斯] 收到通知: 1 + 1 = 2
员工 [ceo 王] 收到通知: 1 + 1 = 2
3. 组合模式总结
组合模式非常适合树形结构的处理,当要求父节点和子节点具有相同的功能的时候。
但Leaf中实现了不必要的方法,客户端不知道操作的节点是Leaf还是Composite,可能导致不安全。
如果抽象组件(例如本例的Node)中仅定义inform方法,而把add、remove、get等放入Composite类中,那么可以避免上述不安全问题;但客户端需要就要区分Leaf和Composite了。
(完)