组合模式是一种结构型设计模式,组合模式将对象以树形结构组合在一起,每一个对象具有相同的属性和方法.组合模式允许客户用统一的方式处理单个对象.

组合模式的特点:

  1. 表示树形结构.可以非常方便描述对象部分-整体层次结构.
  2. 利用对象多态性统一对待组合对象和单个对象.在组合模式中,使用者将统一地使用组合结构中的所有对象,而不用关心它究竟是组合对象还是单个对象.

v2-81c80d516c80c9dbf17f4072c7e8f808_1200x500.jpg

组合模式中每个对象内部结构都应该相同.具体实现内容可以不同._使用者不需要知道当前对象是具体结构是什么,只知道它具备几个固定的方法和属性,直接调用它就行.

在Java语言中,实现组合模式的关键是Composite类和Leaf类必须继承自一个 Compenent抽象类.

代码实现

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
import java.util.ArrayList;
// 抽象构件
abstract class Component {
public abstract void operation();
public void add(Component c) {
throw new UnsupportedOperationException();
}
public void remove(Component c) {
throw new UnsupportedOperationException();
}
public Component getChild(int i) {
throw new UnsupportedOperationException();
}
}
//UnsupportedOperationException 是为了 Leaf 在继承之后不用重写该方法,因为这些方法是 Composite 对象需要重写的,而单个对象不需要。

// Leaf 类:
class ConcreteComponent1 extends Component {
public void operation() {
System.out.println("operation of concrete component 1 ");
}
}

class ConcreteComponent2 extends Component {
public void operation() {
System.out.println("operation of concrete component 2 ");
}
}

class ConcreteComponent3 extends Component {
public void operation() {
System.out.println("operation of concrete component 3 ");
}
}


// 组合类:
class Composite extends Component {
private ArrayList<Component> children;
public Composite() {
children = new ArrayList<Component>();
}
public void operation() {
for(Component child: children) {
child.operation();
}
}

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 class Client {
public static void main(String[] args) {
Component c1 = new ConcreteComponent1();
Component c2 = new ConcreteComponent2();
Component c3 = new ConcreteComponent3();

Component c = new Composite();
c.add(c1);
c.add(c2);
c.add(c3);
c.operation();

c.remove(c2);
c.operation();
}
}

需要注意地方

  • 组合模式不是父子关系.对象之间并不是父子关系
  • 对Leaf对象的操作一致性.组合模式除了要求组合对象和叶对象拥有相同的接口之外,还有一个必要条件,就是对一组叶对象的操作必须具有一致性.
  • 双向映射关系.一个叶对象只在一个组合对象下面,它不能存在多个组合对象中.
  • 用职责链模式提高组合模式的性能.当树的结构比较复杂,节点数量很多的时候,可以借助职责链模式,建立组合对象和叶对象之间的联系.

组合模式适用场景

  1. 表示对象的部分-整体层次结构.组合模式可以方便的构造一棵树表示对象的部分-整体结构.组合模式中增加和删减树的节点非常方便.
  2. 使用者希望统一对待树中的所有对象.组合模式使使用者可以忽略组合对象和叶对象的区别.使用者在面对组合模式的时候,不同关系当前处理的是组合对象还是叶对象.

组合模式缺陷

组合模式会让系统中的每一个对象看起来都差不多,它们的区别只是在运行的时候才会显现出来,会使得代码难以理解.而且组合模式创建了太多的对象,这会增加系统的资源.