组合模式(客户用一致的方式处理对象集合和单个对象)

源码地址 https://github.com/DingMouRen/DesignPattern
组合模式(客户用一致的方式处理对象集合和单个对象)_第1张图片
组合模式.png
  • Component抽象根节点,为组合中的对象声明接口。在适当的情况下,可以实现所有类共有接口的缺省行为。声明一个接口用于访问和管理Component的子节点。(可选)可在递归结构中定义一个接口,用于访问一个父节点,并在适合的情况下实现它。
  • Composite定义有子节点的那些枝干节点的行为,存储子节点,在Component接口中实现与子节点有关的操作
  • Leadf在组合中表示叶子节点的对象,叶子节点没有子节点,在组合中定义节点对象的行为。
定义

组合模式将对象组合成树形结构来表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。

使用场景
  • 表示对象的部分-整体层次结构
  • 从一个整体中能够独立出部分模块或者功能的场景
  • 希望忽略组合对象与单个对象的不同,用户将统一的使用组合结构中的所有对象
协作

用户使用Component类接口 与组合结构中的对象进行交互。如果接收者是一个叶节点,那么久直接处理请求。如果接收者是Composite,它通常将请求发送给它的子部件,在转发请求之前或之后可能执行一些辅助操作。

举个栗子

我们电脑都有这样的结构:文件夹与文件,这是典型的组合模式的例子,这是透明的组合模式,叶节点与枝干节点有相同的结构,安全的组合模式请看源码中的例子。

组合模式(客户用一致的方式处理对象集合和单个对象)_第2张图片
文件夹与文件.png

//抽象根节点表示文件夹和文件的抽象类
public abstract class Dir {
    //存储文件夹下所有的元素
    protected List dirs = new ArrayList<>();
    //当前文件夹或者文件的名称
    private String name;

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

    //添加一个文件或者文件夹
    public abstract void addDir(Dir dir);
    //移除一个文件或者文件夹
    public abstract void removeDir(Dir dir);
    //清空文件夹下所有的元素
    public abstract void clear();
    //输出文件夹目录结构
    public abstract void showStructure(int level);
    //获取文件夹下所有的文件或者子文件夹
    public abstract List getDirs();
    //获取文件或文件夹名称

    public String getName() {
        return name;
    }
}

//具体实现类,表示文件夹类,但是结构与子节点是一样的,
public class Folder extends Dir {

    public Folder(String name) {
        super(name);
    }

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

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

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

    @Override
    public void showStructure(int level) {
        for (int i = 0; i < level; i++) {
            System.out.print("-");
        }
        System.out.println(getName());
        Iterator iterator = dirs.iterator();
        while (iterator.hasNext()){
            iterator.next().showStructure(level + 3);
        }
    }

    @Override
    public List getDirs() {
        return dirs;
    }
}

//表示文件类,跟文件夹是相同的结构
public class File extends Dir{
    public File(String name) {
        super(name);
    }

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

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

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

    @Override
    public void showStructure(int level) {
        for (int i = 0; i < level; i++) {
            System.out.print("-");
        }
        System.out.println(getName());
    }

    @Override
    public List getDirs() {
        throw new UnsupportedOperationException("文件不支持该操作");
    }
}

使用

    public static void main(String[] args) {
        //构造一个根目录对象C
        Dir diskC = new Folder("C盘");
        //根目录C下添加一个mp3文件
        diskC.addDir(new File("NeedYouNow.mp3"));
        //根目录C下添加三个子目录windows user programfile
        Dir windows = new Folder("windows");
        diskC.addDir(windows);
        Dir user =  new Folder("user");
        diskC.addDir(user);
        Dir programfile = new Folder("programfile");
        diskC.addDir(programfile);
        //windows目录下添加qq.exe文件,user目录下添加info.txt文件,programfile目录下添加触不可及(法国版).mp4
        windows.addDir(new File("qq.exe"));
        windows.addDir(new File("weixin.exe"));
        user.addDir(new File("info.txt"));
        user.addDir(new File("data.txt"));
        programfile.addDir(new File("触不可及(法国版).mp4"));
        programfile.addDir(new File("战狼2.mp4"));
        //打印出根目录结构
        diskC.showStructure(0);
    }
总结

组合模式在android的应用,比如一些界面UI架构的设计,Android目录选择器。

优点:

  • 清晰定义分层次的复杂对象,让高层模块忽略层次的差异,方便对整个层次结构进行控制
  • 简化高层模块的代码,添加枝干构件和叶子构件很方便,符合开闭原则
    缺点:
    在新增构件时不好对枝干中的构件类型进行限制,它们都来自相同的抽象层,所以必须进行类型检查来实现。

你可能感兴趣的:(组合模式(客户用一致的方式处理对象集合和单个对象))