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

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

作者: 钉某人 | 来源:发表于2017-11-17 18:49 被阅读0次
    源码地址 https://github.com/DingMouRen/DesignPattern
    组合模式.png
    • Component抽象根节点,为组合中的对象声明接口。在适当的情况下,可以实现所有类共有接口的缺省行为。声明一个接口用于访问和管理Component的子节点。(可选)可在递归结构中定义一个接口,用于访问一个父节点,并在适合的情况下实现它。
    • Composite定义有子节点的那些枝干节点的行为,存储子节点,在Component接口中实现与子节点有关的操作
    • Leadf在组合中表示叶子节点的对象,叶子节点没有子节点,在组合中定义节点对象的行为。
    定义

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

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

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

    举个栗子

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

    文件夹与文件.png
    //抽象根节点表示文件夹和文件的抽象类
    public abstract class Dir {
        //存储文件夹下所有的元素
        protected List<Dir> 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<Dir> 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<Dir> iterator = dirs.iterator();
            while (iterator.hasNext()){
                iterator.next().showStructure(level + 3);
            }
        }
    
        @Override
        public List<Dir> 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<Dir> 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目录选择器。

    优点:

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

    相关文章

      网友评论

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

          本文链接:https://www.haomeiwen.com/subject/ryzjvxtx.html