一 . 模式动机
- 对于树形结构的,客户端中必须区别对待容器(这里容器指树形结构中不是端点的节点)和叶子对象,而实际上大多数情况下客户端希望一致处理他们。
二 . 模式定义
- 组合模式(Composite Pattern):组合多个对象形成树形结构已表示“整体-部分”的结构层次。组合模式对单个对象(叶子对象)和组合对象(即容器对象)的使用具有一致性。
三 . 模式结构
(图片来源于网络)
- Component:抽象构件
- Composite:容器构建
- Leaf:叶子构建
- Client:客户类
四 . 模式分析
- 组合模式的关键是定义抽象构件,即可以代表叶子,又可以代表容器,客户端针对构件进行编程,无需知道是叶子还是容器,都可以统一处理。
- 聚合关联关系,即在容器构建中引用抽象构件,同时继承或实现抽象构件。
五 . 模式实例
-
最经典的组合模式实例就是文件系统,文件可以分为文件夹,还有各种类型的文件,形成一个树形结构。这里我们简单实现一下遍历文件结构中的文件。
-
实例UML图
(图片来源于网络) -
抽象构件和叶子构件
public abstract class File {
void display(){
}
void add() {
}
void remove(){
}
}
class VideoFile extends File {
void display(){
System.out.println("这是VideoFile文件");
}
}
class TextFile extends File {
void display(){
System.out.println("这是Text文件");
}
}
class ImageFile extends File {
void display(){
System.out.println("这是Image文件");
}
}
- 容器构件
import java.util.ArrayList;
public class Folder extends File {
ArrayList<File> files = new ArrayList();
public void display(){
for(File file:files){
file.display();
}
}
public void add(File file){
files.add(file);
}
public void remove(File file){
files.remove(file);
}
}
- 测试类
public class Client {
public static void main(String[] args) {
File f1,f2,f3,f5;
f1 = new ImageFile();
f2 = new TextFile();
f3 = new VideoFile();
Folder f4 = new Folder();
f5 = new Folder();
//这里的文件结构是f4文件夹下有ImageFile,和子文件夹
//子文件夹里有TextFile和VideoFile
f4.add(f1);
f4.add(f5);
((Folder) f5).add(f2);
((Folder) f5).add(f3);
f4.display();
}
}
- 测试结果
E:\Java\jdk1.8.0_171\bin\java.exe "-javaagent:E:\idea\IntelliJ IDEA 2019.1.3\lib\idea_rt.jar=57302:E:\idea\IntelliJ IDEA 2019.1.3\bin" -Dfile.encoding=UTF-8 -classpath "E:\Java\jdk1.8.0_171\jre\lib\charsets.jar;E:\Java\jdk1.8.0_171\jre\lib\deploy.jar;E:\Java\jdk1.8.0_171\jre\lib\ext\access-bridge-64.jar;E:\Java\jdk1.8.0_171\jre\lib\ext\cldrdata.jar;E:\Java\jdk1.8.0_171\jre\lib\ext\dnsns.jar;E:\Java\jdk1.8.0_171\jre\lib\ext\jaccess.jar;E:\Java\jdk1.8.0_171\jre\lib\ext\jfxrt.jar;E:\Java\jdk1.8.0_171\jre\lib\ext\localedata.jar;E:\Java\jdk1.8.0_171\jre\lib\ext\nashorn.jar;E:\Java\jdk1.8.0_171\jre\lib\ext\sunec.jar;E:\Java\jdk1.8.0_171\jre\lib\ext\sunjce_provider.jar;E:\Java\jdk1.8.0_171\jre\lib\ext\sunmscapi.jar;E:\Java\jdk1.8.0_171\jre\lib\ext\sunpkcs11.jar;E:\Java\jdk1.8.0_171\jre\lib\ext\zipfs.jar;E:\Java\jdk1.8.0_171\jre\lib\javaws.jar;E:\Java\jdk1.8.0_171\jre\lib\jce.jar;E:\Java\jdk1.8.0_171\jre\lib\jfr.jar;E:\Java\jdk1.8.0_171\jre\lib\jfxswt.jar;E:\Java\jdk1.8.0_171\jre\lib\jsse.jar;E:\Java\jdk1.8.0_171\jre\lib\management-agent.jar;E:\Java\jdk1.8.0_171\jre\lib\plugin.jar;E:\Java\jdk1.8.0_171\jre\lib\resources.jar;E:\Java\jdk1.8.0_171\jre\lib\rt.jar;E:\Design pattern\out\production\Design pattern" Composite.Client
这是Image文件
这是Text文件
这是VideoFile文件
Process finished with exit code 0
六 . 模式优缺点
- 优点
- 可以清楚定义分层次的复杂对象,定义包含叶子节点和容器对象的类层次结构,可以形成复杂的树形结构。
- 客户端可以一致的使用组合结构或其中单个对象。
- 很容易在组合体内加入对象构件,符合“”扩展性强。
- 缺点
- 使设计变得更抽象,对业务规则如果很复杂,则实现组合模式具有很大挑战性。
- 增加新构件很难对容器中的构件控制。
七 . 模式使用环境
- 需要表示一个对象整体或部分层次。
- 想让客户忽略不同对象层次的变化。
- 客户需要一直处理不同层次的对象。
八 . 模式应用
- XML文档解析
- 文件系统结构
九 . 模式扩展
- 透明组合模式:叶子构件也必须实现add(),remove()等方法。
- 安全组合模式:抽象构件中无需定义add(),等方法,只需在容器构件中定义add()等方法即可。