软件体系结构-组合模式

定义

组合多个对象形成树形结构以表示具有部分-整体关系的层次结构。组合模式让客户端可以统一对待单个对象和组合对象。

UML类图

包含三个部分:抽象构件、叶子构件和容器构件

代码实现

抽象构件:

1
2
3
4
5
6
public abstract class AbstractNode {
public abstract void addNode(AbstractNode node);
public abstract void removeNode(AbstractNode node);
public abstract AbstractNode getNode(int i);
public abstract void handleMessage(String msg);
}

叶子构件:

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
public class UserNode extends AbstractNode{

@Override
public void addNode(AbstractNode node) {
try {
throw new Exception("UserNode不支持addNode");
} catch (Exception e) {
e.printStackTrace();
}
}

@Override
public void removeNode(AbstractNode node) {
try {
throw new Exception("UserNode不支持removeNode");
} catch (Exception e) {
e.printStackTrace();
}
}

@Override
public AbstractNode getNode(int i) {
try {
throw new Exception("UserNode不支持getNode");
} catch (Exception e) {
e.printStackTrace();
}
return null;
}

@Override
public void handleMessage(String msg) {
System.out.println("处理消息:"+msg);
}
}

容器构件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class GroupNode extends AbstractNode{
private ArrayList<AbstractNode> nodeList = new ArrayList<AbstractNode>();

@Override
public void addNode(AbstractNode node) {
nodeList.add(node);
}

@Override
public void removeNode(AbstractNode node) {
nodeList.remove(node);
}

@Override
public AbstractNode getNode(int i) {
return nodeList.get(i);
}

@Override
public void handleMessage(String msg) {
System.out.println("处理消息:"+msg);
}
}

透明组合与安全组合模式

透明组合模式:

  • 抽象构件Component中声明了所有用于管理成员对象的方法,包括add()、remove(),以及getChild()等方法
  • 在客户端看来,叶子对象与容器对象所提供的方法是一致的,客户端可以一致地对待所有的对象
  • 缺点是不够安全,因为叶子对象和容器对象在本质上是有区别的

安全组合模式:

  • 抽象构件Component中没有声明任何用于管理成员对象的方法,而是在Composite类中声明并实现这些方法

  • 对于叶子对象,客户端不可能调用到这些方法

  • 缺点是不够透明,客户端不能完全针对抽象编程,必须有区别地对待叶子构件和容器构件

优点

在具体实现时,可以创建图形化界面让用户来选择所需操作的根节点,无须修改源代码,符合开闭原则

  • 可以清楚地定义分层次的复杂对象,表示对象的全部或部分层次,让客户端忽略了层次的差异,方便对整个层次结构进行控制
  • 客户端可以一致地使用一个组合结构或其中单个对象,不必关心处理的是单个对象还是整个组合结构,简化了客户端代码
  • 增加新的容器构件和叶子构件都很方便,符合开闭原则
  • 为树形结构的面向对象实现提供了一种灵活的解决方案

缺点

  • 在增加新构件时很难对容器中的构件类型进行限制

适用

  • 在具有整体和部分的层次结构中,希望通过一种方式忽略整体与部分的差异,客户端可以一致地对待它们
  • 在一个使用面向对象语言开发的系统中需要处理一个树形结构
  • 在一个系统中能够分离出叶子对象和容器对象,而且它们的类型不固定,需要增加一些新的类型