组合模式
组合模式(composite pattern)也称为“整体-部分(Part-Whole)”模式,允许你将对象组合成树形结构来表现"整体-部分"层次结构,使得客户对单个对象和组合对象使用具有一致性,属于结构性模式。
组合关系和聚合关系的区别:
1、组合关系:比如车和轮胎,也可以认为是全体 - 部分的关系,车报废时,轮胎也跟着报废 。(具有相同的生命周期)
part-of关系,父类拥有子类,子类不能独立于父类存在。
2、聚合关系:班级和学生是一种聚合关系。一个班级,可以有学生,也可以没有学生;反过来,当我们把班级解散,学生仍然存在。(具有不同的生命周期)
has-a关系,父类包含子类,子类可以独立于父类存在。
组合模式一般用来描述整体和部分的关系,它将对象组织到树形结构中,最顶层的节点称为根节点,根节点下面包含树枝节点和叶子节点,树枝节点下面又可以包含树枝节点和叶子节点。

组合模式的包含3个角色:
抽象根节点(Component):定义系统各层次对象的共有方法和属性,可以预先定义一些默认的属性和行为;
树枝节点(Composite):定义了树枝节点的节点,组合树枝节点和叶子节点形成一个树形结构;
叶子类(Leaf):叶子节点的对象,其下再无分支,是系统层次遍历的最小单元。
组合模式在代码的具体的实现上,有两种不同的方式,分别是透明组合模式和安全组合模式。
组合模式应用场景
1、希望客户端可用忽略组合对象和单个对象的差异;
2、对象层次具备整体和部分,呈现树形结构;
在我们的生活中组合模式也非常常见,比如树形菜单,操作系统目录结构,公司组织架构等。
透明组合模式
透明组合模式是把公共方法定义在Component 中,这样做的好处是客户端无需分辨是叶子节点和树枝节点,它们具有一样的接口,UML类图如下:

Component类:
public abstract class Component { protected String name; protected int level; public Component(String name,int level) { this.name = name; this.level = level; } abstract void print(); abstract public void add(Component component); abstract public void remove(Component component);}Composite类:
public class Composite extends Component { private List child; public Composite(String name, int level) { super(name, level); child = new ArrayList<>(); } @Override void print() { for (int i = 0; i < level; i++) { System.out.print("##"); } System.out.println("Composite:" + name); for (Component component : child) { component.print(); } } @Override public void add(Component component) { child.add(component); } @Override public void remove(Component component) { child.remove(component); }}Leaf类:
public class Leaf extends Component { public Leaf(String name, int level) { super(name, level); } @Override void print() { for (int i = 0; i < level; i++) { System.out.print("##"); } System.out.println("leaf:" + name); } @Override public void add(Component component) { // 牺牲透明性换取单一职责原则,这样就不用考虑是叶子节点还是组合节点 throw new UnsupportedOperationException(); } @Override public void remove(Component component) { throw new UnsupportedOperationException(); }}Client类:
public class Client { public static void main(String[] args) { Composite root = new Composite("root",0); Component node1 = new Leaf("1",1); Component node2 = new Composite("2",1); Component node3 = new Leaf("3",1); root.add(node1); root.add(node2); root.add(node3); Component node21 = new Leaf("21",2); Component node22 = new Composite("22",2); node2.add(node21); node2.add(node22); Component node221 = new Leaf("221",3); node22.add(node221); root.print(); }}运行结果:
Composite:root##leaf:1##Composite:2####leaf:21####Composite:22######leaf:221##leaf:3透明组合模式是把所有公共方法都定义在Component中,这样做的好处是客户端无需分辨是叶子节点还是树枝节点,它们是一样的接口;缺点是叶子节点会继承一些用不到的方法,这种方式违背了接口隔离原则。
下面我们来看下安全组合模式的写法。
安全组合模式
安全组合模式只是规定系统各个层次的最基础的一致行为,而把组合(树节点)本身的方法(添加、删除)放大自身当中,UML类图如下:

修改Component类:
public abstract class Component { protected String name; protected int level; public Component(String name,int level) { this.name = name; this.level = level; } abstract void print();}修改Leaf类:
public class Leaf extends Component { public Leaf(String name, int level) { super(name, level); } @Override void print() { for (int i = 0; i < level; i++) { System.out.print("##"); } System.out.println("leaf:" + name); }}从上面可以看出,Component减少了添加和删除节点方法,因为叶子节点是不需要的,没有必要实现了。
组合模式的优缺点
优点:
1、清楚定义了分层次的复杂对象,表示对象的全部和部分的层次
2、客户端不必担心层次的差异,方便对整个层次结构的控制
3、简化客户端代码
4、符合开闭原则
缺点:
1、限制类的时候会比较复杂
2、设计变得更加抽象
-END-关注公众号,不错过每一篇原创干货

本文介绍了组合模式,它允许将对象组合成树形结构,表现“整体 - 部分”层次。阐述了组合与聚合关系的区别,介绍了组合模式的角色,包括抽象根节点、树枝节点和叶子类。还讲解了透明和安全两种实现方式,分析了其优缺点及应用场景。

9898

被折叠的 条评论
为什么被折叠?



