组合模式

341 阅读3分钟

组合模式

##定义 将对象组合成树形结构表示整体-部分的层次结构,使得用户对每个单个对象和组合对象的使用具有一致性

##使用场景 表示对象的部分-整体层次结构时 从一个整体中能够独立出部分模块或功能的场景

##模式结构

  • Component 抽象根节点,为组合中的对象声明接口
  • Composite 定义有子节点的那些枝干节点的行为,存储子节点,在 Component 接口中实现与子节点有关的操作
  • Leaf 在组合中表示叶子节点对象,叶子节点没有子节点,在组合中定义节点对象的行为
  • Client 通过 Component 接口操纵组合节点的对象

##简单实现 操作系统的文件系统就是一种典型的组合模式例子,Android中View与ViewGroup构成的UI体系也是很典型的实现。 下面以一个简单的文件系统来做说明

public abstract class Dir {

    /**
     * 声明一个 list 成员变量存储文件夹下的所有元素
     */
    protected List<Dir> dirs = new ArrayList<>();

    private String name;

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

    /**
     * 添加一个文件或文件夹
     *
     * @param dir 文件或文件夹
     */
    public abstract void addDir(Dir dir);

    /**
     * 删除一个文件或文件夹
     *
     * @param dir 文件或文件夹
     */
    public abstract void rmDir(Dir dir);

    /**
     * 清空文件夹下所有元素
     */
    public abstract void clear();

    /**
     * 输出文件夹目录结构
     */
    public abstract void print();

    /**
     * 获取文件夹下所有文件或子文件夹
     *
     * @return 文件夹下所有文件或子文件夹
     */
    public abstract List<Dir> getFiles();


    /**
     * 获取文件或文件夹名
     *
     * @return 文件或文件夹名
     */
    public String getName() {
        return name;
    }
}

public class File extends Dir {
    public File(String name) {
        super(name);
    }

    @Override
    public void addDir(Dir dir) {
        throw new UnsupportedOperationException("文件对象不支持该操作");
    }

    @Override
    public void rmDir(Dir dir) {
        throw new UnsupportedOperationException("文件对象不支持该操作");
    }

    @Override
    public void clear() {
        throw new UnsupportedOperationException("文件对象不支持该操作");
    }

    @Override
    public void print() {
        System.out.print(getName());
    }

    @Override
    public List<Dir> getFiles() {
        throw new UnsupportedOperationException("文件对象不支持该操作");
    }
}

文件为叶子节点,不能作为文件夹来使用,它相对于文件夹来说既不支持添加也不支持删除,这里直接抛出一个不支持异常来简单处理。

public class Folder extends Dir {
    public Folder(String name) {
        super(name);
    }

    @Override
    public void addDir(Dir dir) {
        dirs.add(dir);
    }

    @Override
    public void rmDir(Dir dir) {
        dirs.remove(dir);
    }

    @Override
    public void clear() {
        dirs.clear();
    }

    @Override
    public void print() {
        System.out.print(getName() + " (");

        Iterator<Dir> iterator = dirs.iterator();
        while (iterator.hasNext()) {
            Dir dir = iterator.next();
            dir.print();
            if (iterator.hasNext()) {
                System.out.print(", ");
            }
        }
        System.out.print(") ");
    }

    @Override
    public List<Dir> getFiles() {
        return dirs;
    }
}

public class Client {

    public static void main(String[] args) {

        Dir disk = new Folder("木叶");
        File file = new File("火影");
        disk.addDir(file);

        Dir high = new Folder("上忍");
        disk.addDir(high);

        Dir low = new Folder("下忍");
        disk.addDir(low);

        Dir elite = new Folder("精英上忍");
        high.addDir(elite);
        elite.addDir(new File("卡卡西 "));

        Dir general = new Folder("普通上忍");
        high.addDir(general);
        general.addDir(new File("宁次"));

        low.addDir(new File("鸣人"));
        low.addDir(new File("佐助"));


        disk.print();


        System.out.println("\n---------------------\n");

        disk.rmDir(file);

        disk.print();

    }
}

输出结果:

木叶 (火影, 上忍 (精英上忍 (卡卡西 ) , 普通上忍 (宁次) ) , 下忍 (鸣人, 佐助) ) 
---------------------

木叶 (上忍 (精英上忍 (卡卡西 ) , 普通上忍 (宁次) ) , 下忍 (鸣人, 佐助) ) 
Process finished with exit code 0