组合模式(Composite Pattern)

一、定义

组合模式(Composite Pattern):结构型模式之一,组合多个对象形成树形结构以表示“整体-部分”的关系的层次结构。组合模式对叶子节点和容器节点的处理具有一致性,又称为整体-部分模式

二、UML类图

在这里插入图片描述

三、角色职责

  • 抽象构件(Component):叶子构件与容器构件共同继承的父类或者是共同实现的接口,该角色中包含所有子类共有方法的声明和实现,在抽象构件中定义了管理子构件的方法,新增构件、删除构件、获取构件。
  • 叶子构件(Leaf):表示叶子节点,没有子节点,对于继承父类的管理子节点的方法以抛出异常的方式处理。
  • 容器构件(Composite):表示容器节点,包含子节点,子节点可以是容器节点也可以是叶子节点,其提供一个集合来对子节点进行维护,以迭代的方式对子节点进行处理。

四、代码实现

前言:现在疫情形势异常严峻,那各个省市的疾控中心是怎样收到的通知,又是怎样下发的呢?首先是中央层面的中国疾控中心,这是所有疾控中心的上级,他会将命令下发给省级的疾控中心,然后省级的疾控中心收到通知后,又会下发给市级的疾控中心,这样依次下发到区、县、镇、村…如果应用到代码层面,这就是组合模式。

抽象构件 Component

public interface Unit {
    void add(Unit unit);
    void remove(Unit unit);
    Unit getChild(int i);
    void sendMessage(String message);
}

容器构件 Composite

@Data
@NoArgsConstructor
public class Subsidiary implements Unit {
    private List<Unit> units = new ArrayList<>();
    private String name;
    public Subsidiary(String name) {
        this.name = name;
    }
    @Override
    public void add(Unit unit) {
        units.add(unit);
    }
    @Override
    public void remove(Unit unit) {
        units.remove(unit);
    }
    @Override
    public Unit getChild(int i) {
        return units.get(i);
    }
    @Override
    public void sendMessage(String message) {
        System.out.println(name + "收到通知");
        System.out.println(name + "下发通知");
        units.forEach(child -> child.sendMessage(message));
    }
}

疾控中心 (叶子构件 Leaf)

@Data
@NoArgsConstructor
@AllArgsConstructor
public class CDC implements Unit {
    private String name;
    @Override
    public void add(Unit unit) {
        System.out.println(name + "没有子节点");
    }
    @Override
    public void remove(Unit unit) {
        System.out.println(name + "没有子节点");
    }
    @Override
    public Unit getChild(int i) {
        System.out.println(name + "没有子节点");
        return null;
    }
    @Override
    public void sendMessage(String message) {
        System.out.println(name + "收到通知");
    }
}

测试类

public class CompositePattern {
    public static void main(String[] args) {
        // 中国疾控中心
        Unit head = new Subsidiary("中国疾控中心");
        // 江苏疾控中心
        Unit jsCDC = new Subsidiary("江苏疾控中心");
        head.add(jsCDC);
        // 南京疾控中心
        Unit njCDC = new CDC("南京疾控中心");
        jsCDC.add(njCDC);
        // 徐州疾控中心
        Unit xzCDC = new CDC("徐州疾控中心");
        jsCDC.add(xzCDC);
        // 广东疾控中心
        Unit gdCDC = new Subsidiary("广东疾控中心");
        head.add(gdCDC);
        // 广州疾控中心
        Unit gzCDC = new CDC("广州疾控中心");
        gdCDC.add(gzCDC);
        // 东莞疾控中心
        Unit dgCDC = new CDC("东莞疾控中心");
        gdCDC.add(dgCDC);
        head.sendMessage("全民戴口罩");
    }
}

输出结果

中国疾控中心收到通知
中国疾控中心下发通知
江苏疾控中心收到通知
江苏疾控中心下发通知
南京疾控中心收到通知
徐州疾控中心收到通知
广东疾控中心收到通知
广东疾控中心下发通知
广州疾控中心收到通知
东莞疾控中心收到通知

五、源码分析

在这里插入图片描述
在Mybatis中,就适用到了组合模式。
在这里插入图片描述
SqlNode接口有很多的实现类,他们就一级节点。
在这里插入图片描述
我们随便点进一个一级节点TrimSqlNode,可以看到二级节点WhereSqlNode。
在这里插入图片描述
Mybatis在处理动态SQL节点时,应用到了组合设计模式,MyBatis会将映射文件中定义的静态SQL节点、文本节点等解析成对应的SqlNode实现,形成树形结构。

六、优缺点分析

优点

  • 节点自由增加。使用了组合模式后,如果想增加一个树枝节点、树叶节点十分简单,只要找到它的父节点就成,非常容易扩展,符合开闭原则,有利于后期维护。

缺点

  • 树枝树叶直接使用了实现类,这在面向接口编程上是很不恰当的,与依赖倒置原则冲突,限制了接口的影响范围。

七、适用场景

在一个系统中能够分离出叶子对象和容器对象,而且它们的类型不固定,需要增加—些新的类型时,可以使用组合模式。

八、总结

组合模式使用面向对象的思想来实现树形结构的构建与处理,描述了如何将容器对象和叶子对象进行递归组合,实现简单,灵活性好。由于在软件开发中存在大量的树形结构,因此组合模式是一种使用频率较高的结构型设计模式。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值