教朋友写责任链

背景

最近一个开发的朋友开始学习Java,她之前写脚本语言多一点,对于面向对象的一些设计还是不够熟练,她写一个代码特别的累,需要大量堆if-else语句,她的直觉告诉她这样写肯定不够好,然后咨询了我。

场景介绍

她的代码逻辑是要处理一个BinlogDTO的Message消息,然后做一些后续的逻辑,由于前面的设计是很多张表都会沿用这个BinlogDTO对象并且发送的一个Message的Topic,这个BinlogDTO的对象大概定义为:

class BinlogDTO {
    private String tableName;
    //....其他省略
}

并且MQ使用的RocketMQ消息中间件,她这边的逻辑是要根据每个表和不同的tag去处理
在这里插入图片描述
发现这个表非常多,而且后续可能持续不断的添加新的表,每个圆圈就代表一个变化的逻辑。所以很正常会包含大量的if-else。

思考

这个问题本质就是区分变化的纬度,这里发现表的数量是一个重要的维度,如果不加以管控,大量的判断语句无法避免,回想23种设计模式,有没有一种方式能解决这种场景,我认为这里抓住两个要点,我们处理的统一对象是一个消息,处理的逻辑是需要判断的,最好能解耦消息的接收和消息的处理,那很自然就会想到责任链模式了。
在这里插入图片描述

回顾下责任链模式的UML图
在这里插入图片描述
调用者逻辑
在这里插入图片描述

实践

接下来就是代码实现
定义BinlogDTO对象,也是Message封装的消息体结构

class BinlogDTO implements Serializable {
    private String tableName;
    //....setter getter 省略
}

定义消息处理的Handler,是一种能力的抽象,后面新加表,就是基于此能力进行扩展

interface BinlogHandler {
    /**
     * 处理消息的tag is null
     * @param message
     */
    void processIgnore(Message message);

    /**
     * 处理tag 不为 null
     * @param message
     */
    void processMergeTag(Message message);

    /**
     * 获取表名
     * @return
     */
    String getTableName();
}

定义模板抽象类,是否当前Handler处理这个逻辑是一个可以固定下来的逻辑,因此可以写个模板,包括后期各个Handler可以复用的方法也可以放在此基类里面

abstract class AbstractBinlogHandler implements BinlogHandler {

    public boolean isMatch(Message message) {
        return getTableName().equals(getTableName(message));
    }

    private String getTableName(Message message) {
        // TODO 获取message 里的的table
        BinlogDTO binlogDTO = SerializationUtils.deserialize(message.getBody());
        return binlogDTO.getTableName();
    }
}

接下来定义具体的处理Handler,真正干活,扩展的东西,后面新添加表,只需要继承AbstractBinlogHandler去实现对应的tag实现即可,当然也要表明自己的表名,与消息体里的tableName一致。

class TableAHandler extends AbstractBinlogHandler {

    @Override
    public void processIgnore(Message message) {
        System.out.println("proccsse table a ignore tag");
    }

    @Override
    public void processMergeTag(Message message) {
        System.out.println("processe table a merge tag");
    }

    @Override
    public String getTableName() {
        return "tableA";
    }
}

class TableBHandler extends AbstractBinlogHandler {
    @Override
    public void processIgnore(Message message) {
        System.out.println("proccsse table b ignore tag");
    }

    @Override
    public void processMergeTag(Message message) {
        System.out.println("processe table b merge tag");
    }

    @Override
    public String getTableName() {
        return "tableB";
    }
}

接下来定义责任链的处理,就是解耦消息的消费与处理受体的解耦:

class BinlogHandlerChain {

    private static List<AbstractBinlogHandler> binlogHandlerList = new ArrayList<>();

    static {
        // load all handler
        // 可以利用 Spring的注入机制
        TableAHandler tableAHandler = new TableAHandler();
        TableBHandler tableBHandler = new TableBHandler();
        binlogHandlerList.add(tableAHandler);
        binlogHandlerList.add(tableBHandler);
    }

	/**
	 * 这里就是任务的提交,客户端只用调这里即可,不用关心去调谁了
	 */
    public void doSubmit(Message message) {
        // 找出对应表匹配的handler
        List<AbstractBinlogHandler> handlerList = binlogHandlerList.stream().filter(e -> e.isMatch(message)).collect(Collectors.toList());
        /*
        分别处理tag和不需要的tag
         */
        if (message.getTag() == null) {
            handlerList.forEach(e -> e.processIgnore(message));
        } else {
            handlerList.forEach(e -> e.processMergeTag(message));
        }
    }
}

使用
模拟tableA的binlog带标签和不带标签使用

    public static void main(String[] args) {
        Message message = new Message();

        /*
        构造消息
         */
        BinlogDTO binlogDTO = new BinlogDTO();
        binlogDTO.setTableName("tableA");
        message.setBody(SerializationUtils.serialize(binlogDTO));

        /*
        处理消息
         */
        BinlogHandlerChain binlogHandlerChain = new BinlogHandlerChain();
        // tag is null
        binlogHandlerChain.doSubmit(message);

        // tag is not null
        message.setTag("tagA");
        binlogHandlerChain.doSubmit(message);
    }

输出:
processe table a merge tag
proccsse table a ignore tag

扩展
新来的表只用新建类
class tableX extends AbstractBinlogHandler 即可。
在这里插入图片描述

总结&思考

可能会发现我写的责任链跟标准的责任链有些不一样,例如标准的责任链是关注链条顺序的,我并不关心,因此不需要控制它的顺序。这就是学习设计模式的正确意义,它传递的是一种抽象思想,而不是具体实现,结合实际业务的变种才是设计模式正确的实践方式。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值