likes
comments
collection
share

设计模式Java实现-组合模式

作者站长头像
站长
· 阅读数 1

✨这里是第七人格的博客✨小七,欢迎您的到来~✨

🍅系列专栏:设计模式🍅

✈️本篇内容:组合模式✈️

🍱本篇收录完整代码地址:gitee.com/diqirenge/d…🍱

楔子

小七最近工作可以说是忙到飞起,本来想着今天休息一下就不再更新了。但是!但是!但是!

今天下午居然被群友推荐鼓励了o( ̄▽ ̄)ブ,那必须得再干它一篇!

设计模式Java实现-组合模式

ps:有些朋友觉得设计模式太简单了,希望小七聊聊JUC和Spring源码。小七只想说不要方(●ˇ∀ˇ●),等设计模式这个专栏写完了,就开始更新JUC相关知识。

大纲都已经有了,可以浏览小七的github-page尝尝鲜 li-zong-yang.github.io/#/guide_ind…

需求背景

2022年小七研究过一段时间的接口编排,当时还给liteFlow提过一个Issues

设计模式Java实现-组合模式

Issues中举例的业务场景就很适合使用组合模式。

我们再将这个需求简单描述一下:

1、我们有2种检验注册的手段 a.手机号 b身份证

2、这两种校验手段在不同的业务场景下,有不同的组合,可以都参与校验,也可以只有一个参与校验。

分析设计

为了让我们的校验功能,能够进⾏⾃由组合对外提供服务。我们可以把这两种校验手段想象成两片叶子,他们可以自由组合成一棵完整的树。

设计模式Java实现-组合模式

首先我们抽象出组件接口ComponentChecker,让两个具体的校验类都实现它;

然后我们定义组合节点Composite,可以先理解成图中的root,它里面要包含子节点,所以我们得有一个list的属性

/**
 * 可以存放子节点
 */
private List<ComponentChecker> children;

UML图

根据分析设计,我们可以先画一个简单的UML图,后面通过UML图编码

设计模式Java实现-组合模式

模块名称

composite

模块地址

gitee.com/diqirenge/d…

模块描述

组合模式代码示例

代码实现

1、定义组件接口

/**
 * 定义组件接口
 * 关注公众号【奔跑的码畜】,一起进步不迷路
 *
 * @author 第七人格
 * @date 2023/11/30
 */
public interface ComponentChecker {
    /**
     * 校验
     */
    void check();
}

具体实现子类-身份证校验器

/**
 * 子节点 - 身份证校验器
 * 关注公众号【奔跑的码畜】,一起进步不迷路
 *
 * @author 第七人格
 * @date 2023/11/30
 */
class IdCardChecker implements ComponentChecker {
    private String number;

    public IdCardChecker(String number) {
        this.number = number;
    }

    @Override
    public void check() {
        System.out.println("校验身份证[" + number + "]被执行了...");
    }

    @Override
    public String toString() {
        return "IdCard{" +
                "number='" + number + '\'' +
                '}';
    }
}

具体实现子类-电话校验器

/**
 * 子节点 - 电话校验器
 * 关注公众号【奔跑的码畜】,一起进步不迷路
 *
 * @author 第七人格
 * @date 2023/11/30
 */
class PhoneChecker implements ComponentChecker {
    private String number;

    public PhoneChecker(String number) {
        this.number = number;
    }

    @Override
    public void check() {
        System.out.println("校验电话号码[" + number + "]被执行了...");
    }

    @Override
    public String toString() {
        return "Phone{" +
                "number='" + number + '\'' +
                '}';
    }
}

2、定义组合节点

关键点是要将组件接口的集合作为属性放到类中

/**
 * 定义组合节点
 * 关注公众号【奔跑的码畜】,一起进步不迷路
 *
 * @author 第七人格
 * @date 2023/11/30
 */
class Composite implements ComponentChecker {
    private String name;
    /**
     * 可以存放子节点
     */
    private List<ComponentChecker> children;

    public Composite(String name) {
        this.name = name;
        this.children = new ArrayList<>();
    }

    /**
     * 添加子节点
     *
     * @param child 添加的节点
     */
    public void addChild(ComponentChecker child) {
        children.add(child);
    }

    /**
     * 移除子节点
     *
     * @param child 删除的节点
     */
    public void removeChild(ComponentChecker child) {
        children.remove(child);
    }

    @Override
    public void check() {
        System.out.println("组合节点[" + name + "]准备开始执行\n叶子节点数据为:" + children.toString() + "\n");
        for (ComponentChecker child : children) {
            child.check();
        }
    }

    @Override
    public String toString() {
        return "Composite{" +
                "name='" + name + '\'' +
                ", children=" + children +
                '}';
    }
}

3、编写测试类

/**
 * 测试组合模式
 * 关注公众号【奔跑的码畜】,一起进步不迷路
 *
 * @author 第七人格
 * @date 2023/11/29
 */
public class CompositeTest {
    @Test
    public void testBridge() {
        // 创建根节点,他是一个组合节点
        Composite root = new Composite("根节点");

        // 创建叶子节点1
        IdCardChecker leaf1 = new IdCardChecker("500383*********");
        root.addChild(leaf1);

        // 创建叶子节点2
        PhoneChecker leaf2 = new PhoneChecker("186*********");
        root.addChild(leaf2);

        // 执行操作
        root.check();
    }
}

5、测试结果

组合节点[根节点]准备开始执行

叶子节点数据为:[IdCard{number='500383 * * * * * * * * * '}, Phone{number='186 * * * * * * * * *'}]

校验身份证[500383 * * * * * * * * * *]被执行了...

校验电话号码[186* * * * * * * * * * * *]被执行了...

实现要点

  1. 抽象组件(Component):定义创建对象的接口,允许客户端独立地获取组件对象。

    文中示例为:ComponentChecker

  2. 叶子节点(Leaf):继承/实现自抽象组件,表示叶子节点对象。

    文中示例为:IdCardChecker和PhoneChecker

  3. 容器节点(Composite):继承自抽象组件,表示容器节点对象,包含子组件列表。

    文中示例为:Composite;子组件列表为:private List children。

总结

组合模式是一种结构型设计模式,它将对象组织成树形结构,使得客户端可以以统一的方式处理单个对象和组合对象。