组合模式

……

问题描述

大学院系结构项目

每个大学都有不同的学院,而不同的学院又有不同的专业。大学里可以增加或移除学院,学院里也可以增加移除专业,存在相同的层次结构。

组合模式(Composite Pattern)

模式概述

允许将对象组合成树形结构来表现“整体/部分”层次结构。组合能让客户以一致的方式处理个别对象以及组合对象。

组合模式就是在一个对象中包含其他对象,这些被包含的对象可能是终点对象(不再包含别的对象),也有可能是非终点对象(其内部还包含其他对象,或叫组对象),我们将对象称为节点,即一个根节点包含许多子节点,这些子节点有的不再包含子节点,而有的仍然包含子节点,以此类推。

模式组件

  • 抽象组件(Component):可以是接口或者抽象类,是叶子构件和容器构件的接口,包含子类行为的声明和实现。
  • Leaf(叶子节点):叶子节点没有子节点,实现了抽象构件定义的行为,也就是说,一个列表有一个节点,节点已经是最低级的了,叶子节点就不可以再有叶子节点或树枝节点了。
  • Composite(树枝节点):树枝节点中含所有子节点,节点可以是子节点,也可以是树枝节点,是一个集合,用来存储节点的。

优点

  1. 简化客户端操作。客户端只需要面对一致的对象而不用考虑整体部分或者节点叶子的问题。
  2. 具有较强的扩展性。当我们要更改组合对象时,我们只需要调整内部的层次关系,客户端不用做出任何改动。
  3. 便创建出复杂的层次结构。客户端不用理会组合里面的组成细节,容易添加节点或者叶子从而创建出复杂的树形结构。

缺点

  1. 叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则。
  2. 要求较高的抽象性,如果节点和叶子有很多差异性的话,比如很多方法和属性都不一样,难以实现组合模式。

注意事项

  1. 建议当需要遍历组织机构,或者处理的对象具有树形结构时使用组合模式。
  2. 每个组件均为定义时为具体类。

####简单组合架构代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.kevin.结构型模式.组合模式.composite;

/**
* @author kevin
* @version 1.0
* @description 抽象组件
* @createDate 2019/2/27
*/
public interface Component {

void operation();
}

// 叶子组件
interface Leaf extends Component {

}

// 容器组件
interface Composite extends Component {
void add(Component c);
void remove(Component c);
Component getChild(int index);
}

###模拟杀毒软件架构设计
####抽象构件角色:

1
2
3
4
5
// 抽象构建
public interface AbstractFile {

void killVirus();
}

####叶子组件:

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
package com.kevin.结构型模式.组合模式.composite;

import java.util.ArrayList;
import java.util.List;

/**
* @author kevin
* @version 1.0
* @description 抽象构建
* @createDate 2019/2/27
*/
public interface AbstractFile {

void killVirus();
}

// 叶子组件
class ImageFile implements AbstractFile {

private String name;

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

@Override
public void killVirus() {
System.out.println("图像文件: "+name+",进行查杀");
}
}

// 叶子组件
class TextFile implements AbstractFile {

private String name;

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

@Override
public void killVirus() {
System.out.println("文本文件: "+name+",进行查杀");
}
}

// 叶子组件
class VideoFile implements AbstractFile {

private String name;

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

@Override
public void killVirus() {
System.out.println("视频文件: "+name+",进行查杀");
}
}


####容器组件:

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
// 容器组件
class Folder implements AbstractFile {

private String name;

// 定义容器,用来存放本容器构建的子节点
private List<AbstractFile> list = new ArrayList<>();

public void add(AbstractFile file) {
list.add(file);
}

public void remove(AbstractFile file) {
list.remove(file);
}

public AbstractFile getChild(int index) {
return list.get(index);
}

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

@Override
public void killVirus() {
System.out.println("文件夹: " + name + ",进行查杀");

for (AbstractFile file : list) {
file.killVirus(); // 递归
}
}


}

####测试组合模式:

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
package com.kevin.结构型模式.组合模式.composite;

/**
* @author kevin
* @version 1.0
* @description 测试组合模式,相对适合树形结构时使用
* @createDate 2019/1/18
*/
public class Test {

public static void main(String[] args) {

AbstractFile f2,f3;

Folder f1 = new Folder("我的收藏");
f2 = new ImageFile("照片.jpg");
f3 = new TextFile("Hello.txt");

f1.add(f2);
f1.add(f3);

//f2.killVirus();

f1.killVirus();
}
}

开发中的应用场景:
– 操作系统的资源管理器
– GUI中的容器层次图
– XML文件解析
– OA系统中,组织结构的处理
– Junit单元测试框架
– 底层设计就是典型的组合模式,TestCase(叶子)、TestUnite(容器)
– Test接口(抽象)