设计模式之组合模式(Java实现)
Composite(组合)
一、意图
将对象组合成树型结构以表示“部分-整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性。
二、结构
组合模式的结构如图7.33所示。 其中: • Component为组合中的对象声明接口;在适当情况下实现所有类共有接口的默认行为; 声明一个接口用于访问和管理Component的子组件;(可选)在递归结构中定义一个接口,用于访问一个父组件,并在合适的情况下实现它。 • Leaf在组合中表示叶结点对象,叶结点没有子结点;在组合中定义图元对象的行为。 • Composite定义有子组件的那些组件的行为;存储子组件;在Component接口中实现与子组件有关的操作。 • Client通过Component接口操纵组合组件的对象。
三、适用性
Composite模式适用于: • 想表示对象的部分-整体层次结构。 • 希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。
四、实现
现欲构造一文件/目录树,采用组合(Composite)设计模式来设计,得到的类图如下图 所示: 首先 创建抽象文件类。
abstract class AbstractFile { protected String name; //文件或目录名称 public void printName() { System.out.println(name); } //给一个目录增加子目录或文件 public abstract boolean addChild(AbstractFile file); //删除一个目录的子目录或文件 public abstract boolean removeChild(AbstractFile file); //获得一个目录的子目录或文件 public abstract List<AbstractFile> getChildren(); }
然后 创建文件类和文件夹类分别继承抽象文件类。
class File extends AbstractFile { public File(String name) { this.name = name; } public boolean addChild(AbstractFile file) { return false; } public boolean removeChild(AbstractFile file) { return false; } public List<AbstractFile> getChildren() { return null ; } } class Folder extends AbstractFile { private List<AbstractFile> childList; //存储子目录或文件 public Folder(String name) { this.name = name; this.childList = new ArrayList<AbstractFile>(); } public boolean addChild(AbstractFile file) { return childList.add(file); } public boolean removeChild(AbstractFile file) { return childList.remove(file); } public List <AbstractFile> getChildren() { return childList ; } }
最后 测试一下。
public class Composite { public static void main(String[] args) { // TODO Auto-generated method stub // 创造一个树形的文件/目录结构 AbstractFile rootFolder = new Folder("c:\"); AbstractFile compositeFolder = new Folder("composite"); AbstractFile windowsFolder = new Folder("windows"); AbstractFile file = new File("TestComposite.java"); rootFolder.addChild(compositeFolder); rootFolder.addChild(windowsFolder); compositeFolder.addChild(file); // 打印目录文件数 printTree(rootFolder); } private static void printTree(AbstractFile ifile) { ifile.printName(); List<AbstractFile> children = ifile.getChildren(); if (children == null) return; for (AbstractFile file : children) { printTree(file) ; } } }
运行结果: