本文将介绍设计模式中的组合模式。
一、什么是组合模式?
在软件中,常常可以见到树形结构,对于开发人员而言,我们希望的是:
可以一致地处理非叶节点和叶子节点两种组成元素
因为对它们的区别处理会使程序复杂度增加
对某个节点调用业务方法时,能够自行进行递归调用
以免在外部额外书写树的递归访问代码
此时便可以运用组合模式,它使用户可以同一对待单个对象和组合对象。
二、实现
1. 结构
2. 角色
- Component 抽象构件:
- 叶子构件和容器构件的接口
- 定义了 Composite 容器构件访问和管理子构件的行为
- 定义了 Leaf 叶子构件进行的业务操作
- Leaf 叶子构件:
- 表示叶子节点
- 没有子节点
- 由于 Component 抽象构件中定义了访问和管理子构件的行为,但这些行为实际上是不存在于 Leaf 叶子构件中的,因此可以通过异常等方式进行处理
- 实现了业务操作
- Composite 容器构件:
- 表示容器节点
- 包含子节点,其子节点可以是叶子节点,也可以是容器节点
- 实现了 Component 抽象构件中定义的访问和管理子构件的行为
- 本身不进行业务操作,会通过遍历调用的方法,调用所有子节点的业务操作
3. 简单示例
Component:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| 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(); }
|
Leaf:
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
| public class Leaf extends Component {
public void add(Component component) { }
public void remove(Component component) { }
public Component getChild(int index) { return null; }
public void operation() { ··· } }
|
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
| public class Composite extends Component { private List<Component> list = new ArrayList<>();
public void add(Component component) { list.add(component); }
public void remove(Component component) { list.remove(component); }
public Component getChild(int index) { return list.get(index); }
public void operation() { for (Component component : list) { list.operation(); } } }
|
三、安全组合模式
在安全组合模式中,
- Component 抽象构件声明业务方法,
- Leaf 叶子构件实现业务方法
- Composite 容器构件在业务方法中遍历调用子元素的业务方法
- Component 抽象构件不会声明访问和管理子构件的方法,
- Composite 容器构件自行书写访问和管理子构件的方法
在这种做法下,Leaf 不需要额外书写无用的方法,外界也不必对异常调用做处理,是更安全的方式。
但是这个方法存在的问题是:客户端需要区别对待两种元素,其代码复杂性将增加。
四、优缺点
1. 优点
- 客户端无需区别对待叶子节点和非叶节点两种元素,降低了代码复杂性
- 客户端无需书写树形结构的访问代码
参考