• 9、设计模式之组合模式(Composite)


    一、什么是组合模式
    组合模式也成为整体部分模式,是一种结构型设计模式。它将对象组合成树形的层次结构,用来表示“整体-部分”的关系。通过组合模式,我们可以使用相同的方式处理单个对象和多个对象组合。

    二、角色组成

    组件(Component):定义组合模式中所有对象共有的方法和属性。
    叶子节点(Leaf):叶子节点对象,也是组合中没有子节点的对象。
    组合节点(Composite):表示组合中的容器对象,该对象包含其他子节点。

    三、优缺点
    优点:

    通过组合模式,可以使客户端统一处理单个对象和组合对象,并且不用区分类型,简化了客户端代码的复杂性。
    在无需修改现有的代码情况下,可以很容易地增减新的组件类型,更加灵活。
    组合对象和单个对象之间的一致性接口可以使代码更易复用
    缺点:

    可能限制组件的类型:组合模式要求组件和叶子节点具有相同的接口,这可能会限制组件的类型。例如,所有的组件都必须实现相同的操作,即使某些组件并不需要这些操作。
    对某些操作的不支持:在组合模式中,对于某些操作,可能只有叶子节点能够支持,而组合对象不能够支持。这可能需要在设计时进行权衡。
    可能增加系统复杂性:虽然组合模式可以简化客户端代码,但在另一方面,它也引入了新的类和关系,可能增加了系统的复杂性。在一些简单的情况下,使用组合模式可能会显得过于繁琐。
    四、应用场景
    4.1 生活场景
    古代皇帝:皇帝治理国家不可能具体到某一个人,所以设置了很多机构,比如三省六部,这些机构下面又有很多小的组织,它们共同治理这个国家。
    公司:一个公司下面有很多小部门,每个部门下面又分好几个组,有可能再细点每个组又分为职业不同的人(前端、测试、开发、运维)。
    文件:比如C盘、D盘下面有很多文件夹,文件夹里面又有很多文件或文件夹。
    4.2 java场景

    HashMap:putAll()传入的是Map对象,Map就是一个组件,而HashMap就是一个组合节点,HashMap中的Node节点就是叶子节点。同理,ArrayList对象也有addAll()方法。
    Java AWT和SWING:对于Button和Checkbox是叶子节点,Container是组合节点。

    五、代码实现
    下面以算数表达式为例,解释一下组合模式。我们可以把算数表达式看作是一个树状结构,由操作符和操作数组成。

    组件(Component):Expression
    叶子节点(Leaf):AddOperator、MulOperator、Number
    组合节点(Composite):Operator

    5.0 UML类图
    在这里插入图片描述
    5.1 Expression-组件(Component)

    /**
     * 
     * 1.组件(Component):算数表达式
     */
    public interface Expression {
     
        //求值
        double evaluate();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    5.2 Number-叶子节点(Leaf)

    /**
     * 
     * 2.叶子节点(Leaf):数字
     */
    public class Number implements Expression{
        private double val;
        public Number(double v){
            this.val=v;
        }
     
        @Override
        public double evaluate() {
            return val;
        }
    }
    
    /**
     * 
     * 2.叶子节点(Leaf):加法操作符
     */
    public class AddOperator extends Operator{
        public AddOperator(Expression left, Expression right) {
            super(left, right);
        }
     
        @Override
        public double evaluate() {
            return left.evaluate() + right.evaluate();
        }
    }
    /**
     * 
     * 2.叶子节点(Leaf):加法操作符
     */
    public class MulOperator extends Operator{
        public MulOperator(Expression left, Expression right) {
            super(left, right);
        }
     
        @Override
        public double evaluate() {
            return left.evaluate() * right.evaluate();
        }
    }
    
    • 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
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    5.3 Operation-组合节点(Composite)

    /**
     * 
     * 2.组合节点(Composite):运算
     */
    public abstract class Operator implements Expression{
        protected Expression left;
        protected Expression right;
     
        public Operator(Expression left, Expression right) {
            this.left = left;
            this.right = right;
        }
    //    @Override
    //    public double evaluate(){
    //        return 0;
    //    }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    5.4 testComposite

    /**
     * 
     * 组合模式测试类
     */
    @SpringBootTest
    public class TestComposite {
       @Test
        void testComposite(){
            // 构建一个算数表达式: (2 + 3) * 4
            Expression expression = new MulOperator(
                    new AddOperator(new Number(2), new Number(3)),
                    new Number(4)
            );
            // 计算表达式的结果
            double result = expression.evaluate();
            System.out.println("(2+3)*4=" + result);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    六、总结
    组合模式通过把叶子节点当成特殊的组合节点来看待,从而对叶子节点和组合节点能用相同的方式处理,下面总结一下组合模式在程序设计中的使用场景:

    对象的层次结构:当你有一组对象,这些对象可以以层次结构的方式进行组织时,组合模式非常有用。例如,文件系统中的文件和文件夹、组织架构中的部门和员工等。
    统一处理对象:当你希望能够以统一的方式处理一组对象时,组合模式可以派上用场。组合模式会将叶子对象和组合对象统一对待,这样你就可以通过递归遍历整个对象树,从而对每个对象进行相同的操作。
    部分-整体关系:组合模式非常适用于表示部分-整体关系的情况。你可以将单个对象视为整体,将多个对象组合成部分,然后再将多个部分组合成更大的整体,以此类推。
    可以忽略对象的具体类型:通过使用组合模式,你可以忽略对象的具体类型,只处理对象的共同接口。这样可以简化代码,使其更加灵活、可扩展和易于维护。

  • 相关阅读:
    Java Spring框架 (底层原理+入门)
    HTML CSS 网页设计作业「体育小站」(梅西足球 6页 )
    <学习笔记>从零开始自学Python-之-web应用框架Django( 九)自定义标签和过滤器
    MHA实现MySQL主从的高可用
    CDN,DNS,ADN,SCDN,DCDN,ECDN,PCDN,融合CDN的介绍
    基于FPGA的智能小车系统
    Spring-boot Mybatis-plus 实战应用
    Apache Spark 中的 RDD是什么
    最强大脑记忆曲线(12)-- 录入数据修改
    oracle定时任务的使用
  • 原文地址:https://blog.csdn.net/weixin_45817985/article/details/136651920