◉◡◉ 您好,欢迎到访伊成个人站!

java设计模式之组合模式

组合模式介绍

又叫整体-部分模式,它是一种将对象组合成树状的层次结构的模式,用来表示“整体-部分”的关系,使用户对单个对象和组合对象具有一致的访问性,属于结构型设计模式。

组合模式一般用来描述整体与部分的关系,它将对象组织到树形结构中,顶层的节点被称为根节点,根节点下面可以包含树枝节点和叶子节点,树枝节点下面又可以包含树枝节点和叶子节点,树形结构图如下。

“伊成博客”

组合模式UML类图

“伊成博客”

模式构造

Component: 抽象构件。
Leaf: 叶子构件。
Composite: 容器构件。

组合模式分为 透明式 的组合模式和 安全式的组合模式。

(1) 透明方式

在该方式中,由于抽象构件声明了所有子类中的全部方法,所以客户端无须区别树叶对象和树枝对象,对客户端来说是透明的。但其缺点是:树叶构件本来没有 Add()、Remove() 及 GetChild() 方法,却要实现它们(空实现或抛异常),这样会带来一些安全性问题。其结构图如图 1 所示。

“伊成博客”

(2) 安全方式

在该方式中,将管理子构件的方法移到树枝构件中,抽象构件和树叶构件没有对子对象的管理方法,这样就避免了上一种方式的安全性问题,但由于叶子和分支有不同的接口,客户端在调用时要知道树叶对象和树枝对象的存在,所以失去了透明性。其结构图如图 2 所示。

“伊成博客”

举个例子

下面就演示两种模式的实例的demo。

透明组合模式

下面为透明式的组合模式的实现代码。

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
public class CompositePattern {
public static void main(String[] args) {
Component c0 = new Composite();
Component c1 = new Composite();
Component leaf1 = new Leaf("1");
Component leaf2 = new Leaf("2");
Component leaf3 = new Leaf("3");
c0.add(leaf1);
c0.add(c1);
c1.add(leaf2);
c1.add(leaf3);
c0.operation();
}
}

//抽象构件
interface Component {
public void add(Component c);

public void remove(Component c);

public Component getChild(int i);

public void operation();
}

//树叶构件
class Leaf implements Component {
private String name;

public Leaf(String name) {
this.name = name;
}

public void add(Component c) {
}

public void remove(Component c) {
}

public Component getChild(int i) {
return null;
}

public void operation() {
System.out.println("树叶" + name + ":被访问!");
}
}

//树枝构件
class Composite implements Component {
private ArrayList<Component> children = new ArrayList<Component>();

public void add(Component c) {
children.add(c);
}

public void remove(Component c) {
children.remove(c);
}

public Component getChild(int i) {
return children.get(i);
}

public void operation() {
for (Object obj : children) {
((Component) obj).operation();
}
}
}

运行结果:

1
2
3
树叶1:被访问!
树叶2:被访问!
树叶3:被访问!

安全组合模式

安全式的组合模式与透明式组合模式的实现代码类似,只要对其做简单修改就可以了,代码如下。

首先修改 Component 代码,只保留层次的公共行为。

1
2
3
interface Component {
public void operation();
}

然后修改客户端代码,将树枝构件类型更改为 Composite 类型,以便获取管理子类操作的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class CompositePattern {
public static void main(String[] args) {
Composite c0 = new Composite();
Composite c1 = new Composite();
Component leaf1 = new Leaf("1");
Component leaf2 = new Leaf("2");
Component leaf3 = new Leaf("3");
c0.add(leaf1);
c0.add(c1);
c1.add(leaf2);
c1.add(leaf3);
c0.operation();
}
}

组合模式的优缺点

优点

  • 高层模块调用简单。一棵树形机构中的所有节点都是Component,局部和整体对调用者来说没有任何区别,高层模块不必关心自己处理的是单个对象还是整个组合结构。
  • 符合“开闭原则”。在组合模式中新增叶子构件和容器构件都很方便。

    缺点

  • 使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒转原则。

应用场景

前面分析了组合模式的结构与优缺点点,下面分析它适用的以下应用场景。

  • 在需要表示一个对象整体与部分的层次结构的场合。
  • 要求对用户隐藏组合对象与单个对象的不同,用户可以用统一的接口使用组合结构中的所有对象的场合。

组合模式使用案例

  1. JDK中AWT包和Swing包的设计是基于组合模式 ,在这些界面包中为用户提供了大量的容器构件(如 Container )和成员构件(如 Checkbox 、 Button 和 TextComponent 等),他们都是继承、关联自抽象组件类Component。

2.JDK中的Container类和HashMap类。

“伊成博客”

通过看它的行为方法add()可以看出,它添加的是它的父类,符合组合模式的设计

“伊成博客”


The end.

支付宝打赏 微信打赏