• 组合模式


    思考组合模式

    组合模式实际上就是让客户端不再区分操作的是组合对象还是叶子对象,而是以一个统一的方式来操作。

    1.组合模式的本质

    组合模式的本质:统一叶子对象和组合对象。

    组合模式通过把叶子对象当成特殊的组合对象看待,从而对叶子对象和组合对象一视同仁,全部当成了Component对象,有机地统一了叶子对象和组合对象。
    正是因为统一了叶子对象和组合对象,在将对象构建成树型结构的时候,才不需要做区分,反正是组件对象里面包含其他的组件对象,如此递归下去;也才使得对于树形结构的操作变得简单,不管对象类型,统一操作。

    2.何时选用组合模式

    建议在以下情况中选用组合模式。

    • 如果你想表示对象的部分—整体层次结构,可以选用组合模式,把整体和部分的操作统一起来,使得层次结构实现更简单,从外部来使用这个层次结构也容易。
    • 如果你希望统一地使用组合结构中的所有对象,可以选用组合模式,这正是组合模式提供的主要功能。

    3.优缺点

    组合模式有以下优点。

    • 定义了包含基本对象和组合对象的类层次结构
      在组合模式中,基本对象可以被组合成复杂的组合对象,而组合对象又可以组合成更复杂的组合对象,可以不断地递归组合下去,从而构成一个统一的组合对象的类层次结构。

    • 统一了组合对象和叶子对象
      在组合模式中,可以把叶子对象当作特殊的组合对象看待,为它们定义统一的父类,从而把组合对象和叶子对象的行为统一起来。

    • 简化了客户端调用
      组合模式通过统一组合对象和叶子对象,使得客户端在使用它们的时候,不需要再去区分它们,客户不关心使用的到底是什么类型的对象,这就大大简化了客户端的使用。

    • 更容易扩展
      由于客户端是统一地面对Component来操作,因此,新定义的Composite或 Leaf子类能够很容易地与已有的结构一起工作,而客户端不需要为增添了新的组件类而改变。

    4.组合模式的结构

    在这里插入图片描述

    • Component:抽象的组件对象,为组合中的对象声明接口,让客户端可以通过这个接口来访问和管理整个对象结构,可以在里面为定义的功能提供缺省的实现。
    • Leaf:叶子节点对象,定义和实现叶子对象的行为,不再包含其他的子节点对象。
    • Composite:组合对象,通常会存储子组件,定义包含子组件的那些组件的行为,并实现在组件接口中定义的与子组件有关的操作。
    • Client:客户端,通过组件接口来操作组合结构里面的组件对象。

    5.实现

    一个学校有多个学院,一个学院有多个专业,抽象成一个树形结构
    学校和学院都可以有叶子节点,可以共用一个类(Composite),叶子节点单独用一个类(Leaf)
    在这里插入图片描述

    1.父接口

    /**
     * @description:父接口
     */
    @Data
    public abstract class Component {
    
        /**
         * 打印
         * @param preStr
         */
        public abstract void print(String preStr);
    
        /**
         * 添加对象
         * @param component
         */
        public void add(Component component){
            throw new UnsupportedOperationException("对象不支持这个功能");
        }
    
        /**
         * 移除对象
         * @param component
         */
        public void remove(Component component){
            throw new UnsupportedOperationException("对象不支持这个功能");
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    2.组合对象类

    /**
     * @description:组合对象(学校、学院)
     */
    public class Composite extends Component {
    
        private String name;
    
        private List<Component> list = new ArrayList<>();
    
        public Composite(String name) {
            this.name = name;
        }
    
        @Override
        public void print(String preStr) {
            System.out.println(preStr+"+"+this.name);
            if (this.list!=null){
                preStr+=" ";
                for (Component c: list){
                    c.print(preStr);
                }
            }
        }
    
        @Override
        public void add(Component component) {
            list.add(component);
        }
     
        @Override
        public void remove(Component component) {
            list.remove(component);
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    3.叶子类

    /**
     * @description:叶子对象(系)
     */
    @AllArgsConstructor
    public class Leaf extends Component {
    
        /**
         * 叶子节点名字
         */
        private String name;
    
        @Override
        public void print(String preStr) {
            System.out.println(preStr+"-"+name);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    4.测试类

    public class Client {
    
    
        public static void main(String[] args) {
            //学校
            Component university = new Composite("清华大学");
            //学院
            Component computerCollege = new Composite("计算机学院");
            Component mathCollege = new Composite("数学学院");
    
            //学院添加系
            computerCollege.add(new Leaf("软件"));
            computerCollege.add(new Leaf("电子"));
            computerCollege.add(new Leaf("通信"));
            mathCollege.add(new Leaf("概率"));
            mathCollege.add(new Leaf("统计"));
    
            //学校添加学院
            university.add(computerCollege);
            university.add(mathCollege);
    
            //输出学校结构
            university.print("");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    在这里插入图片描述
    这样就实现了类似树形结构
    在这里插入图片描述

  • 相关阅读:
    IP代理与加速器:理解它们的区别与共同点
    代码质量与安全 | 想在发布竞赛中胜出?Sonar来帮你
    Kubernetes容器运行时:Containerd vs Docke
    .NET Emit 入门教程:第六部分:IL 指令:3:详解 ILGenerator 指令方法:参数加载指令
    django接入djangorestframework-simplejwt步骤
    LeetCode二叉树系列——145.二叉树的后序遍历
    五、运算符
    【大数据】-- flink kubernetes operator 入门与实践
    Docker常见命令
    别再死记硬背JVM参数了!实战“双十一”大促,亲手调教服务器
  • 原文地址:https://blog.csdn.net/qq_42665745/article/details/128152091