组合模式是指将对象组合成树形结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性。
在平时,我们在应用中碰到的文件系统(文件是叶子节点,文件目录是树枝节点,可以包含文件或文件目录);企业结构(企业有很多部门,部分有些是没有下属部门,有些是有的);另外,还有向分类层级关系等,这些都可以看做是组合模式的典型应用。
一. 组合模式的基本介绍
意图
将对象组合成树形结构以表示“部分-整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性。
结构
组合模式的基本结构如下:
这里涉及到的参与者有如下几种:
- Component角色
- 这是一抽象角色,它给参加组合的对象规定一个接口,规范共有的接口及默认行为。
- Leaf角色
- 在组合中表示叶节点对象,叶子节点没有子节点。
- Composite角色
- 代表参加组合的有子对象的对象,定义出这样的对象的行为。
- Client角色
- 通过Component接口操纵组件的对象
参与者如何协作?
用户使用Component类接口与组合结构中的对象进行交互。如果接收者是一个叶子节点,则直接处理请求。如果接收者是Composite,它通常将请求发送给它的子部件,在转发请求之前与/或之后可能执行一些辅助操作。
二. 组合模式的示例
接下来以一个文件、目录的示例来说明一下组合模式。其中File是叶子节点,Directory是Composite构件。
- Entry(Component角色)
package com.wangmengjun.tutorial.designpattern.composite;
public abstract class Entry {
abstract void add(Entry e);
abstract void list();
}
- File(Leaf角色)
package com.wangmengjun.tutorial.designpattern.composite;
public class File extends Entry {
private String name;
public File(String name) {
this.name = name;
}
@Override
public void list() {
System.out.println(name);
}
/**
* @return the name
*/
public String getName() {
return name;
}
@Override
void add(Entry e) {
//叶子节点不能添加子节点,dothing
}
}
- Directory(树枝角色)
package com.wangmengjun.tutorial.designpattern.composite;
import java.util.ArrayList;
import java.util.List;
public class Directory extends Entry {
private String name;
private List<Entry> childEntryList = new ArrayList<>();
public Directory(String name) {
this.name = name;
}
@Override
void add(Entry e) {
childEntryList.add(e);
}
@Override
public void list() {
String currDir = this.getName() "/";
System.out.println(currDir);
for(Entry entry : childEntryList) {
System.out.print(currDir);
entry.list();
}
}
/**
* @return the name
*/
public String getName() {
return name;
}
}
- Client(Client角色)
package com.wangmengjun.tutorial.designpattern.composite;
public class Client {
public static void main(String[] args) {
Entry music = new Directory("音乐");
Entry music1 = new File("冰雨.mp3");
Entry music2 = new File("吻别.mp3");
Entry music3 = new File("等一分钟.mp3");
Entry music4 = new File("小镇姑娘.mp3");
Entry music5 = new File("一千个伤心的理由.mp3");
music.add(music1);
music.add(music2);
music.add(music3);
music.add(music4);
music.add(music5);
Entry enpty = new Directory("空目录");
music.add(enpty);
music.list();
}
}
运行一下:
代码语言:javascript复制音乐/
音乐/冰雨.mp3
音乐/吻别.mp3
音乐/等一分钟.mp3
音乐/小镇姑娘.mp3
音乐/一千个伤心的理由.mp3
音乐/空目录/
三. 小结
优缺点
优点:
(1):组合模式可以很容易地增加新种类的构件
(2):使用组合模式可以使客户端变得容易设计,因为客户端不需要知道构件是树叶构件还是树枝构件。
缺点:
(1):使用组合模式后,控制树枝构件的类型就不太容易
(2):用继承的方法来增加新的行为会变得困难。
参考
[1]. 阎宏. Java与模式.电子工业出版社
[2]. Erich Gamma. 设计模式-可复用面向对象软件的基础. 机械工业出版社.