组合模式:将对象组合成树形结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性。
组合模式 Composite
:通常用于可以使用树状结构描述的场景,比如:
- 公司的组织结构图
公司包含多个部门:行政部,研发部,生产部,以及多个子公司,每个子公司又会有各自的行政部,研发部等,典型的树状结构。
- 操作系统中的文件系统
文件系统包含:文件和文件夹,每个文件夹目录下又可以包含多个子目录及文件。
- 常见的
UI
框架
比如 Android
的 UI
框架中:View
和 ViewGroup
的关系。View
为叶子节点,ViewGroup
为容器,可以包含 View
以及子 ViewGroup
。
组合模式有两种结构:
安全组合模式
类图结构
结构解析
Component
抽象类,定义组合模式中对象的公共接口。
Leaf
叶子节点,实现组合模式中的抽象方法。
Composite
枝干节点,包含多个叶子节点。
示例
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
| public abstract class Component { public abstract void operation(); }
public class Leaf extends Component{ @Override public void operation() { System.out.println("Leaf::operation."); } }
public class Composite extends Component{ private List<Component> componentList = new ArrayList<>();
public void add(Component component){ componentList.add(component); }
public void remove(Component component){ componentList.remove(component); }
public Component getChild(int index){ return componentList.get(index); }
@Override public void operation() { System.out.println("Composite::operation."); for (Component component : componentList){ component.operation(); } } }
public class TestCompositeTypeSafety { public static void main(String[] args) { Composite branch = new Composite(); Leaf branch_leaf1 = new Leaf(); Leaf branch_leaf2 = new Leaf(); branch.add(branch_leaf1); branch.add(branch_leaf2);
Composite root = new Composite(); Leaf leaf = new Leaf(); root.add(leaf); root.add(branch);
root.operation(); } }
Composite::operation. Leaf::operation. Composite::operation. Leaf::operation. Leaf::operation.
|
透明组合模式
类图结构
示例
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
| public abstract class Component { public abstract void add(Component component); public abstract void remove(Component component); public abstract Component getChild(int index); public abstract void operation(); }
public class Leaf extends Component{ @Override public void add(Component component) { throw new UnsupportedOperationException("Cannot add to a leaf."); }
@Override public void remove(Component component) { throw new UnsupportedOperationException("Cannot remove from a leaf."); }
@Override public Component getChild(int index) { throw new UnsupportedOperationException("Cannot getchildfrom a leaf."); }
@Override public void operation() { System.out.println("Leaf::operation."); } }
public class Composite extends Component{ private List<Component> componentList = new ArrayList<>();
@Override public void add(Component component) { componentList.add(component); }
@Override public void remove(Component component) { componentList.remove(component); }
@Override public Component getChild(int index) { return componentList.get(index); }
@Override public void operation() { System.out.println("Composite::operation."); for (Component component : componentList){ component.operation(); } } }
public class TestCompositeUniformity { public static void main(String[] args) { Component branch = new Composite(); Component branch_leaf1 = new Leaf(); Component branch_leaf2 = new Leaf(); branch.add(branch_leaf1); branch.add(branch_leaf2);
Component root = new Composite(); Component leaf = new Leaf(); root.add(leaf); root.add(branch);
root.operation(); } }
Composite::operation. Leaf::operation. Composite::operation. Leaf::operation. Leaf::operation.
|
总结
从两种组合模式的类图结构和示例中,可以看出他们最大的不同在与 Component
:
- 安全组合模式
Component
中并没有将管理子对象抽象出来,也就是不包含 add/remove
等,但是这会导致子对象和组合对象接口不一致。Android View/ViewGroup
就属于安全组合模式。
- 透明组合模式
Component
中将管理子对象抽象到基类中,使得子对象和组合对象具有完全一致的行为接口,但是叶子类实际上并不需要这些管理行为。
优缺点:
- 优点
组合模式可以清楚的定义分层次的复杂对象,高层模块可以忽略层次的差异,调用简单。增加叶子或者树干,不需要修改类库,在客户端就可以实现,符合开闭原则。
- 缺点
组合模式的叶子节点和组合类都是实现类,违反了依赖倒置原则。
参考文档
- 大话设计模式
Android
源码设计模式解析与实战