设计模式之组合模式

什么是组合模式

将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。

组合模式又叫部分-整体模式,理解组合模式就要摸清楚部分和整体的概念。

举个栗子

组合模式的模型图

组合模式有三种角色,下面是编码

  • 抽象构件
1
2
3
4
5
public abstract class Component {
public void operation(){
//共有业务
}
}
  • 叶子构件
1
2
3
4
5
6
public class Leaf extends Component {
@Override
public void operation() {
//重写父类方法
}
}
  • 树枝构件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Composite extends Component {
//构建容器
private ArrayList<Component> componentArrayList = new ArrayList<>();
//添加构件
public void add(Component component) {
componentArrayList.add(component);
}
//删除构件
public void remove(Component component) {
componentArrayList.remove(component);
}
//获取构件集合
public ArrayList<Component> getChildren() {
return componentArrayList;
}
}

三个角色齐了,调用者负责组装整个树形结构,这样就很容易完成了构件的组合,这就是组合模式。不过注意,调用者由于要组装具体的构件,没有办法只依赖于抽象,这是与依赖倒置原则相悖的,我们后面还要讨论。

适用范围

组合模式适合于构建部分和整体的关系,整体和部分可以一致性处理的情况。

优点缺点

组合模式的优点最明显的就是组合及其自由,扩展性特别好,而且部分和整体的处理方式相同,维护简单。

组合模式的缺点也是很明显的,它违反依赖倒置原则,不利于面向接口编程,所以使用时候要权衡。

注意事项

在真实的使用中,数据间关联关系可以存储在关系型数据库中,使用时候直接读取,所以其实不需要担心构建时候的复杂过程。

到此为止,上面讲到的只是组合模式的一种,叫安全模式,组合模式还有一种透明模式,也是比较常见的。

透明的组合模式

透明模式和安全模式的区别很简单,直接看模型图

这就是透明模式,去不就在于构建的方法这次被转移到了抽象构件中。这样处理之后叶子构件和树枝构件在表面上就看不出来区别了,我们需要通过getChildern的返回情况来判断是叶子还是树枝,这样显然没有上一种方法安全,下面是编码。

  • 抽象构件
1
2
3
4
5
6
7
8
9
10
11
public abstract class Component {
public void operation(){
//共有业务
}
//添加构件
public abstract void add(Component component);
//删除构件
public abstract void remove(Component component);
//获取构件集合
public abstract ArrayList<Component> getChildren();
}

树枝构件和上面相同

  • 树叶构件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Leaf extends Component {
//空实现
public void add(Component component) throws UnsupportedOperationException{
throw new UnsupportedOperationException();
}
//空实现
public void remove(Component component) throws UnsupportedOperationException{
throw new UnsupportedOperationException();
}
//空实现
public ArrayList<Component> getChildren() throws UnsupportedOperationException{
throw new UnsupportedOperationException();
}
}

使用了透明模式实现的组合模式是遵循依赖倒置原则的。

最后,组合模式还可以在抽象构件中增加父节点的引用,这样的好处是可以应对反向遍历的需求,具体的编码在此就不演示了。

-------------本文结束感谢您的阅读-------------
坚持原创技术分享,您的支持将鼓励我继续创作!