一天一个设计模式——Composite组合模式

一、模式说明

  能够使容器与内容物具有一致性,创造出递归结构的模式就是Composite组合模式。

  举个例子:计算机中的文件系统中有文件和文件夹的概念,我们知道,文件夹可以包含文件,也可以包含子文件夹,子文件夹中又可以包含文件和文件夹。如果将文件和文件夹都看作“目录条目(Directory Entry)”,那么文件系统就形成了一个递归的容器,这就是一种组合模式。

  更多例子,在Windows操作系统中,一个窗口中可以包含子窗口,从而形成容器的递归;一条宏命令又可以包含另一个宏命令;一个文章章节又可以包含多个子章节。。。这种具有树状结构的数据都适用于组合模式。

二、模式类图

三、代码示例

  在示例程序中,我们创建一个Entry目录条目类,并让File文件类和Dictory文件夹类去继承它。

1、FileTreatementException类

package com.designpattern.cn.Entry;

public class FileTreatementException extends RuntimeException {
    public FileTreatementException(){

    }
    public FileTreatementException(String msg){
        super(msg);
    }
}
View Code

2、Entry条目类

package com.designpattern.cn.Entry;

public abstract class Entry {
    public abstract String getName();
    public abstract int getSize();
    public Entry add(Entry entry) throws FileTreatementException{
        throw new FileTreatementException();
    }
    public void PrintList(){
        printList("");
    }
    protected abstract void printList(String prefix);
    public String toString(){
        return getName() + " (" + getSize() + ")";
    }
}
View Code

3、File文件类

package com.designpattern.cn.Entry;

public class File extends Entry {
    private String name;
    private int size;
    public File(String name, int size){
        this.name = name;
        this.size = size;
    }

    public String getName(){
        return name;
    }

    public int getSize(){
        return size;
    }

    protected void printList(String prefix){
        System.out.println(prefix + "/" + this);
    }
}
View Code

4、Directory目录类

package com.designpattern.cn.Entry;

import java.util.ArrayList;
import java.util.Iterator;

public class Directory extends Entry {
    private String name;
    private ArrayList directory = new ArrayList();
    public Directory(String name){
        this.name = name;
    }
    public String getName(){
        return name;
    }
    public int getSize(){
        int size = 0;
        Iterator it = directory.iterator();
        while (it.hasNext()){
            Entry entry = (Entry) it.next();
            size += entry.getSize();
        }
        return size;
    }
    public Entry add(Entry entry){
        directory.add(entry);
        return this;
    }
    protected void printList(String prefix){
        System.out.println(prefix + "/" + this);
        Iterator it = directory.iterator();
        while (it.hasNext()){
            Entry entry = (Entry) it.next();
            entry.printList(prefix + "/" + name);
        }
    }
}
View Code

5、Main方法类和运行结果

package com.designpattern.cn.Entry;

public class Main {
    public static void main(String[] args) {
        try {
            System.out.println("Making root entries...");
            Directory rootdir = new Directory("root");
            Directory bindir = new Directory("bin");
            Directory tmpdir = new Directory("tmp");
            Directory usrdir = new Directory("usr");

            rootdir.add(bindir);
            rootdir.add(tmpdir);
            rootdir.add(usrdir);
            bindir.add(new File("vi", 10000));
            bindir.add(new File("latex", 20000));
            rootdir.printList("");
        }catch (FileTreatementException e){
            e.printStackTrace();
        }
    }
}
View Code

四、模式中的角色

  • Leaf树叶角色:该角色中不能再放入其他对象,如示例中的File类;
  • Composite复合物类:在其中可以放入Leaf和Composite复合物,如示例程序中的Directory类;
  • Component类:使Leaf和Composite角色具有一致性的角色,如示例中的Entry类;
  • Client客户角色:使用复合模式的对象。

五、相关的设计模式

  • Command模式:Command模式编写宏命令时会使用Composite模式;
  • Vistor访问者模式:可以使用访问者模式访问Composite中的递归结构;
  • Decorator装饰者模式:Composite模式通过Component角色使Composite和Leaf具有一致性,Decorator模式使装饰框和内容具有一致性;
原文地址:https://www.cnblogs.com/zheng-hong-bo/p/11117315.html