一、概述
在面向对象设计时,我们经常遇到一类具有容器特征的对象,它们充当着普通对象的同时,还充当着其它对象的容器,这些对象称为容器对象,而那些只能充当普通对象的对象则称为叶子对象。在容器中既可以包含叶子对象,也可以包含容器对象。例如,在树形目录结构中,包含文件和文件夹两类不同的元素:
2、在文件中不能再包含子文件或者子文件夹
由于容器对象和叶子对象在功能上的区别,在使用这些对象的代码中必须有区别地对待容器对象和叶子对象,而实际上大多数情况下客户端希望一致地处理它们,因为对于这些对象的区别对待将会使程序非常复杂。
如何一致地对待容器对象和叶子对象?我们学个新的模式:组合模式。
组合模式:组合多个对象形成树形结构以表示具有部分和整体关系的层次结构。组合模式让客户端可以统一对待单个对象和组合对象。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(叶子构件)
public abstract void add(Component c); //增加成员
public abstract Component getChild(int i); //获取成员
}
public class Leaf extends Component {
//异常处理或错误提示
}
public void remove(Component c) {
//异常处理或错误提示
}
public Component getChild(int i) {
//异常处理或错误提示
}
public void operation() {
//叶子构件具体业务方法的实现
}
public class Composite extends Component {
private ArrayList<Component> list = new ArrayList<Component>();
public void add(Component c) {
}
public void remove(Component c) {
}
public Component getChild(int i) {
}
public void operation() {
for(Object obj:list) {
}
}
三、案例
某软件公司欲开发一个杀毒(Antivirus)软件,该软件既可以对某个文件夹(Folder)杀毒,也可以对某个指定的文件(File)进行杀毒。该杀毒软件还可以根据各类文件的特点,为不同类型的文件提供不同的杀毒方式,例如图像文件(ImageFile)和文本文件(TextFile)的杀毒方式就有所差异。现使用组合模式来设计该杀毒软件的整体框架。
package com.test;
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
AbstractFile file1,file2, folder ;
folder = new Folder("图像文件");
file2 = new ImageFile("王昭君.gif");
folder .add(file2);
folder.killVirus();
}
}
abstract class AbstractFile {
public abstract void add(AbstractFile file);
public abstract AbstractFile getChild(int i);
}
class Folder extends AbstractFile {
private ArrayList<AbstractFile> fileList=new ArrayList<AbstractFile>();
private String name;
public Folder(String name) {
}
public void add(AbstractFile file) {
fileList.add(file);
}
public void remove(AbstractFile file) {
fileList.remove(file);
}
public AbstractFile getChild(int i) {
return (AbstractFile)fileList.get(i);
}
public void killVirus() {
System.out.println("****对文件夹'" + name + "'进行杀毒"); //模拟杀毒
//递归调用成员构件的killVirus()方法
((AbstractFile)obj).killVirus();
}
}
class ImageFile extends AbstractFile {
private String name;
public ImageFile(String name) {
}
public void add(AbstractFile file) {
}
public void remove(AbstractFile file) {
}
public AbstractFile getChild(int i) {
return null;
}
public void killVirus() {
//模拟杀毒
System.out.println("----对图像文件'" + name + "'进行杀毒");
}
//TextFile和VideoFile和上述类似,略
运行结果:
本资料案例主要学习 《Java设计模式 中南大学 刘伟》之后总结,其中程序读者亲自在myEclipse8.5版本调试通过,注意本人所有的类和接口写在一个Java文件里面,除了主类其它类和接口不能声明为public的,主要是提醒出道时间不长的读者,以免造成学习上的麻烦,但重在多试,有问题是好事。
组合模式使用的场景:
1、在具有整体和部分的层次结构中,希望通过一种方式忽略整体与部分的差异,客户端可以一致地对待它们
3、在一个系统中能够分离出叶子对象和容器对象,而且它们的类型不固定,需要增加一些新的类型
