前言
组合模式也是结构型模式的一种。
目录

一、定义
组合模式也叫合成模式,或者称部分-整体模式,主要是用来描述部分与整体的关系。
将对象组合成树形结构以表示 “部分-整体” 的层次结构,使得用户对单个对象和组合对象的使用具有一致性。
这里有两个关键点:一个是用树形结构来分层,另一个是通过统一对待来简化操作
二、模式原理分析
模式主要包含三个角色
-
抽象组件:定义需要实现的统一操作。
-
组合节点:代表一个可以包含多个节点的复合对象,意味着在它下面还可以有其他组合节点或叶子节点。
-
叶子节点:代表一个原子对象,意味着在它下面不会有其他节点了。
//抽象组件
public abstract class Component{
public abstract void operation();
}
//叶子节点
public class Leaf extends Component{
@Override
public void operation() {
//叶子节点的操作放这里
}
}
//组合节点
public class Node extends Component {
private List myChildren; //存放子节点列表
@Override
public void operation() {
for (Component component: myChildren) {
component.operation();
}
}
public List getAllMyChildren(){
return this.myChildren;
}
}
结合上面的组合模式模板代码,能大概了解出组合模式封装了以下变化
-
叶子节点和组合节点之间的区别
-
真实的数据结构,树形?网状?
-
遍历真实结构的算法,这里不一定非要for循环遍历
-
结构所使用的一些策略,比如用来汇总的数据
例如创建一个可以生成树形对象功能 (AbstractNode抽象组件中,组合使用的方法都放到了该类,这种称组合模式的透明模式,运行期可能抛异常。还有一种是安全模式,例如上面的模板代码,父类没有子类有的方法,将叶子节点和树枝节点彻底分开。)
//1.定义一个抽象组件 AbstractNode,其中定义节点可以做的操作有:判断是否为根节点、获取节点 id、获取节点关联父节点 id、设置 id、设置父 id、增加、删除节点和获取子节点。
public abstract class AbstractNode {
public abstract boolean isRoot();
public abstract int getId();
public abstract int getParentId();
public abstract void setId(int id);
public abstract void setParentId(int parentId);
public abstract void add(AbstractNode abstractNode);
public abstract void remove(AbstractNode g);
public abstract AbstractNode getChild(int i);
}
//2.创建组合节点 Node,继承自 AbstractNode 实现定义的 8 种接口方法,其中 List 对象 children 用于存放子节点列表。
public class Node extends AbstractNode {
private List<AbstractNode> children;
private int id;
private int pid;
public Node() {
children = new ArrayList<AbstractNode>();
}
@Override
public boolean isRoot() {
return -1 == pid;
}
@Override
public int getId() {
return id;
}
@Override
public int getParentId() {
return pid;
}
@Override
public void setId(int id) {
this.id = id;
}
@Override
public void setParentId(int parentId) {
this.pid = parentId;
}
public void add(AbstractNode c) {
c.setParentId(this.pid+children.size());
c.setId(c.getParentId()+1);
children.add(c);
}
public void remove(AbstractNode c) {
children.remove(c);
}
public AbstractNode getChild(int i) {
return children.get(i);
}
}
//3.创建叶子节点 Leaf,同样继承自 AbstractNode,重写 8 种接口方法,不过,因为叶子节点不能新增和删除节点,所以添加和删除方法不支持,并且获取子节点方法也应该为空
public class Leaf extends AbstractNode {
private int id;
private int pid;
@Override
public boolean isRoot() {
return false;
}
@Override
public int getId() {
return this.id;
}
@Override
public int getParentId() {
return this.pid;
}
@Override
public void setId(int id) {
this.id = id;
}
@Override
public void setParentId(int parentId) {
this.pid = parentId;
}
@Override
public void add(AbstractNode abstractNode) {
throw new UnsupportedOperationException("这个是叶子节点,无法增加");
}
@Override
public void remove(AbstractNode g) {
throw new UnsupportedOperationException("这个是叶子节点,无法删除");
}
@Override
public AbstractNode getChild(int i) {
return null;
}
}
复制代码
场景类
public class Client{
public static void main(String[] args) {
AbstractNode rootNode = new Node();
rootNode.setId(0);
rootNode.setParentId(-1);
AbstractNode node1 = new Node();
node1.add(new Leaf());
node1.add(new Leaf());
rootNode.add(new Leaf());
rootNode.add(new Leaf());
rootNode.add(node1);
System.out.println(node1.getId());
}
}
复制代码
三、使用场景
-
维护和展示部分-整体关系的场景,如树形菜单、文件和文件夹管理
-
统一处理一个结构中的多个对象
-
只要是树形结构,就可以考虑组合模式
四、优点
-
高层模块调用简单
-
清晰定义分层结构
-
快速新增节点,提升组合灵活性
五、缺点
-
难以限制节点类型
-
对依赖导致原则破坏

















![[02/27][官改] Simplicity@MIX2 ROM更新-一一网](https://www.proyy.com/wp-content/uploads/2020/02/3168457341.jpg)


![[桜井宁宁]COS和泉纱雾超可爱写真福利集-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/4d3cf227a85d7e79f5d6b4efb6bde3e8.jpg)

![[桜井宁宁] 爆乳奶牛少女cos写真-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/d40483e126fcf567894e89c65eaca655.jpg)