美文网首页
组合模式(Composite)

组合模式(Composite)

作者: 吉他手_c156 | 来源:发表于2020-04-17 16:57 被阅读0次

    组合(composite)模式的定义,组合模式又叫做 “部分-整体” 模式,他是一种将对象组合成树状层次结构的模式,用来表示 “部分-整体” 的关系,使用户对单个对象和组合对象具有一致的访问性,组合模式属于结构型模式

    组合模式的结构与特点

    1.比如公司的组织架构就是一颗树,总部下来会有财务,行政,人力,研发,市场等部门,每个部门下有会有不同的子部门
    2.在比如文件结构,整体文件结构是一个树形结构,目录和文件,一个目录下面又会有子目录或者文件

    组合模式的使用场景

    1.希望客户端可以忽略组合对象和单个对象的差异是
    2.对象层次具备整体和部分,呈属性结构(如树形菜单,操作系统目录结构,公司组织架构等)

    组合模式的主要角色

    1.抽象构建(Component)角色,主要作用是为树叶和树枝构建声明公共接口,在透明的组合模式中抽象构建还声明和管理子类的接口,在安全模式中组合模式不声明和管理子类的接口,管理工作由树枝构建完成
    2.树叶构建(Leaf)角色,是组合模式中的叶子节点对象,它没有子节点,用于实现抽象构建角色中声明的公共接口
    3.树枝构建(Composite)角色,是组合模式中的分支节点对象,它有子节点,它实现了抽象构建角色中声明的公共接口,主要作用是存储和管理子部件,通常包含 Add(),Remove(),GetChild()等方法

    组合模式都优缺点

    优点
    1.组合模式使得客户端可以一致的访问单个对象或者组合对象,无需关心处理的对象是单个对象,还是组合对象,这简化了客户端的代码
    2.更容易在组合体中加入新的对象,客户端不会因为加入了新的对象而更改源代码,满足开闭原则
    缺点
    1.设计复杂,客户端要花更多的时间去理清类之间的层次关系

    组合模式的实现

    透明组合模式

    创建抽象构建

    /**
     * 抽象构建  Component 透明组合模式
     * 提供树枝和树叶构建公共的接口,并实现它们的默认行为
     * 透明式组合模式还声明访问和管理子类的接口
     * 安全式组合模式将访问和管理子类的接口由树枝构建完成
     */
    public abstract class Component {
        // 树枝和树叶的公共接口
        public abstract void opertation();
    
        // 声明管理子类的接口
        public boolean add(Component component){
            throw new UnsupportedOperationException("不支持添加操作");
        }
        public boolean remove(Component component){
            throw new UnsupportedOperationException("不支持删除操作");
        }
        public Component getChild(int index){
            throw new UnsupportedOperationException("不支持获取操作");
        }
    }
    

    创建树枝构建

    /**
     * 树枝构建 Componsite
     * 是组合模式中的分支构建,它有子节点,实现类抽象构建中公共的接口
     * 主要作用是管理子部件,通常包含 add(),remove,getChild()方法等...
     */
    public class Composite extends Component{
        // 保存子节点
        private List<Component> components = new ArrayList<Component>();
    
        private String name;
        private int level;
        public Composite(String name,int level){
            this.name = name;
            this.level = level;
        }
    
        @Override
        public boolean add(Component component) {
            return components.add(component);
        }
    
        @Override
        public boolean remove(Component component) {
            return components.remove(component);
        }
    
        @Override
        public Component getChild(int index) {
            return components.get(index);
        }
    
        @Override
        public void opertation() {
            System.out.println(this.name);
            for(Component c : this.components){
                for(int i=0;i<level;i++){
                    System.out.print("   ");
                }
                c.opertation();
            }
        }
    }
    

    创建树叶构建

    /**
     * 树叶构建 Leaf 是组合模式中的叶子节点,没有子节点,实现抽象构建中声明的公共接口
     */
    public class Leaf extends Component{
    
        private String name;
    
        public Leaf(String name){
            this.name = name;
        }
    
        @Override
        public void opertation() {
            System.out.println(this.name);
        }
    }
    

    测试

        public static void main(String[] args) {
    
            Component root = new Composite("XXX责任有限公司",1);
            Component leaf = new Leaf("董事长");
            Component c1 = new Composite("财务部", 2);
            Component c2 = new Composite("人事部", 2);
            Component c3 = new Composite("技术部",2);
            root.add(leaf);
            root.add(c1);
            root.add(c2);
            root.add(c3);
    
            Component leaf1 = new Leaf("财务部主管");
            Component leaf2 = new Leaf("人事部主管");
            Component leaf3 = new Leaf("技术部主管");
    
            c1.add(leaf1);
            c2.add(leaf2);
            c3.add(leaf3);
    
            Component c4 = new Composite("技术部员工", 3);
    
            Component emp1 = new Leaf("技术1");
            Component emp2 = new Leaf("技术2");
            Component emp3 = new Leaf("技术3");
    
            c3.add(c4);
    
            c4.add(emp1);
            c4.add(emp2);
            c4.add(emp3);
    
            root.opertation();
        }
    

    结果

    XXX责任有限公司
       董事长
       财务部
          财务部主管
       人事部
          人事部主管
       技术部
          技术部主管
          技术部员工
             技术1
             技术2
             技术3
    

    透明组合模式是把组合使用的方法放到抽象类中,不管叶子对象和树枝对象都是相同的结构,这样做的好处就是叶子节点和树枝节点对于外界没有区别,他们具有完全一致的行为接口,但因为 Leaf 叶子节点类本身并不具备 add(),remove(),getChild()功能,所以实现它是没有意义的,这是就需要使用安全组合模式,它不声明管理子类的接口,声明和管理子类的接口交给子类自己去完成

    安全组合模式

    创建抽象构建,只声明叶子节点和组合节点公共接口,将管理子类的接口,交个子类自己去完成

    /**
     * 安全组合模式
     * 抽象构建 Component 目录类
     * 只声明叶子节点和设置节点公共的接口
     */
    public abstract class Directory {
        protected String name;
        // 声明子类必须实现的构造方法
        public Directory(String name){
            this.name = name;
        }
        // 获取分支下的所有树枝节点和叶子节点
        public abstract void operation(int depth);
    }
    

    创建树枝节点,实现抽象构建的接口,并提供管理子类的方法

    /**
     * 树枝节点 Composite
     * 实现抽象构建的公共接口,声明管理子类的接口
     * 一般包括 add(),remove(),getChild() 等方法
     */
    public class Folder extends Directory{
    
        // 管理组合对象
        private List<Directory> directories = new ArrayList<Directory>();
    
        public Folder(String name) {
            super(name);
        }
    
        public boolean add(Directory directory){
            return this.directories.add(directory);
        }
    
        public boolean remove(Directory directory){
            return this.directories.remove(directory);
        }
    
        public Directory getChild(int index){
            return this.directories.get(index);
        }
        @Override
        public void operation(int depth) {
            // 输出出行结构
            for(int i=0;i<depth;i++){
                System.out.print("- ");
            }
            System.out.println(this.name);
            // 便利下一级节点
            for(Directory d : this.directories){
                d.operation(depth+1);
            }
        }
    }
    

    创建叶子节点,实现抽象构建的方法

    /**
     * 叶子节点 Leaf  文件类
     * 实现抽象构建声明的公共接口
     */
    public class File extends Directory{
    
        public File(String name) {
            super(name);
        }
    
        @Override
        public void operation(int depth) {
            // 输出树形结构
            for(int i=0;i<depth;i++){
                System.out.print("- ");
            }
            System.out.println(this.name);
        }
    }
    

    测试

        public static void main(String[] args) {
            Folder root = new Folder("D:\\盘");
    
            Folder office = new Folder("office组件");
            Directory excel = new File("excel.exe");
            Directory word = new File("word.exe");
            // 添加 office 组件
            office.add(excel);
            office.add(word);
            Directory mp3 = new File("下辈子我还记得你.mp3");
    
            Folder other = new Folder("高清无码...");
            Folder ont = new Folder("【一品道】");
            other.add(ont);
    
    
            Directory m1 = new File("天线宝宝第一集.mp4");
            Directory m2 = new File("天线宝宝第二集.mp4");
            Directory m3 = new File("天线宝宝第三集.mp4");
            ont.add(m1);
            ont.add(m2);
            ont.add(m3);
    
            // 给根目录添加节点
            root.add(office);
            root.add(mp3);
            root.add(other);
    
            root.operation(1);
        }
    

    结果

    - D:\盘
    - - office组件
    - - - excel.exe
    - - - word.exe
    - - 下辈子我还记得你.mp3
    - - 高清无码...
    - - - 【一品道】
    - - - - 天线宝宝第一集.mp4
    - - - - 天线宝宝第二集.mp4
    - - - - 天线宝宝第三集.mp4
    

    相关文章

      网友评论

          本文标题:组合模式(Composite)

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