一.模式定义
组合模式(Composite Pattern):组合多个对象形成树形结构以表示“整体-部分”的结构层次。组合模式对单个对象(即叶子对象)和组合对象(即容器对象)的使用具有一致性。
Composite Pattern: Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.
二.模式要素
Component: 抽象构件
Leaf: 叶子构件
Composite: 容器构件
Client: 客户类
三.举例说明
文件系统就是典型的树状结构。如果遇到普通文件或者图片则是叶节点,如果遇到文件夹,则看其中有无其他文件格式,无就是叶子节点,有的话就是指节点。实现这样一个系统实际上并不难。
四.具体代码
Format.java
package compositePattern;
import java.util.ArrayList;
import java.util.List;
/**
* @program: Test
* @description: 文件格式
* @author: Lei Dong
* @create: 2019-04-21 13:58
**/
public abstract class Format {
List<Format> list = new ArrayList<>();
private String name;
private int depth;
public Format(String name, int depth) {
this.name = name;
this.depth = depth;
}
abstract void add(Format f);
abstract void remove(Format f);
abstract void showDetail();
void showName() {
for (int i = 0; i < depth - 1; i++) {
System.out.print("--");
}
System.out.println(name);
}
}
Image.java
package compositePattern;
/**
* @program: Test
* @description: Image
* @author: Lei Dong
* @create: 2019-04-21 14:06
**/
public class Image extends Format {
public Image(String name, int depth) {
super(name, depth);
}
@Override
void add(Format f) {
}
@Override
void remove(Format f) {
}
@Override
void showDetail() {
showName();
}
}
File.java
package compositePattern;
/**
* @program: Test
* @description: File
* @author: Lei Dong
* @create: 2019-04-21 14:08
**/
public class File extends Format {
public File(String name, int depth) {
super(name, depth);
}
@Override
void add(Format f) {
try {
throw new Exception("无法增加文件格式");
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
void remove(Format f) {
try {
throw new Exception("无法移除文件格式");
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
void showDetail() {
showName();
}
}
Folder.java
package compositePattern;
/**
* @program: Test
* @description: /home
* @author: Lei Dong
* @create: 2019-04-21 14:02
**/
public class Folder extends Format {
public Folder(String name, int depth) {
super(name, depth);
}
@Override
void add(Format f) {
list.add(f);
}
@Override
void remove(Format f) {
if (list.contains(f)) {
list.remove(f);
} else {
try {
throw new Exception("无法移除文件格式");
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Override
void showDetail() {
showName();
for (Format ele : list) {
ele.showDetail();
}
}
}
Main.java
package compositePattern;
/**
* @program: Test
* @description: Main
* @author: Lei Dong
* @create: 2019-04-21 13:56
**/
public class Main {
public static void main(String[] args) {
Folder folder = new Folder("home", 1);
File file = new File("test.txt",2);
Image image = new Image("test.png", 2);
Folder folder1 = new Folder("leidong", 2);
folder.add(file);
folder.add(image);
Image image1 = new Image("haha.png", 3);
File file1 = new File("hehe.txt", 3);
folder1.add(image1);
folder1.add(file1);
folder.add(folder1);
folder.showDetail();
}
}
运行结果:
五.总结
1.组合模式的优点
(1)可以清楚地定义分层次的复杂对象,表示对象的全部或部分层次,使得增加新构件也更容易。
(2)客户端调用简单,客户端可以一致的使用组合结构或其中单个对象。
(3)定义了包含叶子对象和容器对象的类层次结构,叶子对象可以被组合成更复杂的容器对象,而这个容器对象又可以被组合,这样不断递归下去,可以形成复杂的树形结构。
(4)更容易在组合体内加入对象构件,客户端不必因为加入了新的对象构件而更改原有代码。
2.组合模式的缺点
(1)使设计变得更加抽象,对象的业务规则如果很复杂,则实现组合模式具有很大挑战性,而且不是所有的方法都与叶子对象子类都有关联。
(2)增加新构件时可能会产生一些问题,很难对容器中的构件类型进行限制。
3.模式适用环境
在以下情况下可以使用组合模式:
(1)需要表示一个对象整体或部分层次,在具有整体和部分的层次结构中,希望通过一种方式忽略整体与部分的差异,可以一致地对待它们。
(2)让客户能够忽略不同对象层次的变化,客户端可以针对抽象构件编程,无须关心对象层次结构的细节。
(3)对象的结构是动态的并且复杂程度不一样,但客户需要一致地处理它们。