Fork me on Gitee

Composite模式(组合设计模式)

Composite 设计模式?

在计算机的文件系统中,有“文件夹”的概念(在有些操作系统(Linux操作系统)中,也称为“目录”)。文件夹里面既可以放入文件,也可以放入其他文件夹(子文件夹)。在子文件夹中,一样地既可以放入文件,也可以放入子文件夹。可以说,文件夹是形成了一种容器结构、递归结构。

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

  • 关注点:使用Composite模式可以使容器与内容具有一致性,也可以称其为多个和单个的一致性,即将多个对象结合在一起,当作一个对象进行处理。

理清职责

  • 到处存在的递归结构:
  1. 在视窗系统中,一个窗口可以含有一个子窗口,
    2.在文章的列表中,各列表之间可以相互嵌套,这也是一种递归结构。
    3.将多条计算机命令合并为一条宏命令时,如果使用递归结构实现宏命。
    4.树结构的数据结构都适用Composite模式。
  • 实现:演示文件夹 文件子项之间的层次关系
    名字===================>>>说明
    Entry || 抽象类,用来实现File类和Directory类的一致性
    File || 表示文件的类
    Directory || 表示文件夹的类
    FileTreatementException || 表示向文件中增加Entry时发生的异常的类
    Main || 测试程序行为的类

  • Add()方法的存在位置:

  1. 存在Entry 抛出异常。
  2. 存在Entry 中什么也不做。
  3. 声明在Entry中为抽象方法 不去实现。
  4. 直接定义在Directory类中,但是需要关注类型之间的转换。

UML

类图:

Code

  • Entry

···

public abstract class Entry {

/**
 * 1. 文件名
 * 2. 文件大小
 * @return
 */
public abstract String getName();
public abstract int getSize();

/**
 * Directory  增加条目
 * File 不能增加条目
 */
public Entry add(Entry entry)throws FileTreatementException{
    throw new FileTreatementException();
}

public void printList(){
    printList("");
}

protected abstract void printList(String prefix);

@Override
public String toString() {
    return getName()+"("+getSize()+")";
}

}

···

  • File
public class File extends Entry {

    private String name;

    private int size;

    public File(String name, int size) {
        this.name = name;
        this.size = size;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public int getSize() {
        return size;
    }

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


  • Directory

public class Directory extends Entry {

    private String name;

    private List<Entry> directory=new ArrayList<>();

    public Directory(String name) {
        this.name = name;
    }

    @Override
    public Entry add(Entry entry) throws FileTreatementException {
        directory.add(entry);
        return this;
    }

    @Override
    public String getName() {
        return name;
    }

    /**
     * getSize() | printList(String prefix)
     *
     * 都会递归去遍历下面可能存在的 目录或者文件的子项
     */

    @Override
    public int getSize() {
        int size=0;
        Iterator<Entry> it = directory.iterator();
        while (it.hasNext()){
            // 这里的Entry 可能是目录 也可能是文件
            Entry next = it.next();
            size+=next.getSize();
        }

        return size;
    }

    @Override
    protected void printList(String prefix) {
        // 这里的 prefix是一个引用 this将会调用tostring()方法 又会继续调用getName() getSize()方法
        System.out.println(prefix+"/"+this);
        Iterator<Entry> it = directory.iterator();
        while(it.hasNext()){
            // 这里的Entry 可能是目录 也可能是文件
            Entry next = it.next();
            next.printList(prefix+"/"+this);
        }
    }
}



  • FileTreatementException

public class FileTreatementException extends Exception {

    public FileTreatementException() {
    }

    public FileTreatementException(String message) {
        super(message);
    }
}


  • 定义的目的结构:
start +++++++++++
/root(16000)
/root(16000)/bin(16000)
/root(16000)/bin(16000)/vi(1000)
/root(16000)/bin(16000)/notepaid(15000)
/root(16000)/temp(0)
/root(16000)/user(0)

  • MainT
public class MainT {

    public static void main(String[] args) throws FileTreatementException{

        System.out.println("start +++++++++++");

        Directory rootdir=new Directory("root");

        Directory bindir = new Directory("bin");
        Directory tempdir = new Directory("temp");
        Directory userdir = new Directory("user");

        rootdir.add(bindir);
        rootdir.add(tempdir);
        rootdir.add(userdir);

        bindir.add(new File("vi",1000));
        bindir.add(new File("notepaid",15000));

        rootdir.printList();
    }
}

posted @ 2018-10-23 22:58  ---dgw博客  阅读(698)  评论(0编辑  收藏  举报