手撸设计模式之-责任链模式

  • 一 、责任链模式介绍
    • 1.1 定义
    • 1.2 责任链模式UML结构图
    • 1.3 责任链模式结构详细
    • 1.3 用例代码实现
  • 二、责任链模式应用场景:
    • 2.1 场景概述
    • 2.2 场景模式图
    • 2.3 场景代码实现
    • 2.4 优缺点
  • 三、总结

一 、责任链模式介绍

1.1 定义

  • 责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。
  • 在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,直到有对象处理它为止。

1.2 责任链模式UML结构图

1.3 责任链模式结构详细

  1. 抽象处理者(AbstractLogger)角色: 定义一个处理请求的抽象类,包含抽象处理方法和一个后继连接。
  2. 具体处理者(ConsoleLogger)角色: 实现抽象处理者角色,在实现处理者抽象方法,判断能否处理本次请求,如果可以处理请求则进行处理,否则将该请求转给它的后继者。
  3. 客户类(Client)角色: 创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。

1.3 用例代码实现

抽象处理类定义:

public abstract class AbstractLogger {public static int INFO = 1;public static int DEBUG = 2;public static int ERROR = 3;/*** 日志级别*/protected Integer level;/*** 责任链中的下一个元素*/protected AbstractLogger nextLogger;public void setNextLogger(AbstractLogger nextLogger) {this.nextLogger = nextLogger;}public void logMessage(Integer level, String message) {if (this.level <= level) {write(message);}//转发给下一个责任链if (nextLogger != null) {nextLogger.logMessage(level, message);}}/*** 抽象具体写日志方法** @param message*/protected abstract void write(String message);
}

ConsoleLogger级别日志类定义:

public class ConsoleLogger extends AbstractLogger {public ConsoleLogger(Integer level) {this.level = level;}@Overrideprotected void write(String message) {System.out.println("Standard Console::Logger: " + message);}
}

ErrorLogger级别日志类定义:

public class ErrorLogger extends AbstractLogger {public ErrorLogger(Integer level) {this.level = level;}@Overrideprotected void write(String message) {System.out.println("File::Logger: " + message);}
}

FileLogger级别日志类定义:

public class FileLogger extends AbstractLogger {public FileLogger(Integer level) {this.level = level;}@Overrideprotected void write(String message) {System.out.println("File::Logger: " + message);}
}

测试用例定义:

public class ClientTest {private static AbstractLogger getChainOfLoggers(){AbstractLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR);AbstractLogger fileLogger = new FileLogger(AbstractLogger.DEBUG);AbstractLogger consoleLogger = new ConsoleLogger(AbstractLogger.INFO);errorLogger.setNextLogger(fileLogger);fileLogger.setNextLogger(consoleLogger);return errorLogger;}public static void main(String[] args) {AbstractLogger loggerChain = getChainOfLoggers();loggerChain.logMessage(AbstractLogger.INFO, "info");loggerChain.logMessage(AbstractLogger.DEBUG, "debug");loggerChain.logMessage(AbstractLogger.ERROR, "error");}
}

预期输出结果:

Connected to the target VM, address: '127.0.0.1:59791', transport: 'socket'
Standard Console::Logger: info
File::Logger: debug
Standard Console::Logger: debug
Error Console::Logger: error
File::Logger: error
Standard Console::Logger: error
Disconnected from the target VM, address: '127.0.0.1:59791', transport: 'socket'

二、责任链模式应用场景:

2.1 场景概述

像是这些一线电商类的互联网公司,阿里、京东、拼多多等,在618期间都会做一些运营活动场景以及提供的扩容备战,就像过年期间百度的红包一样。但是所有开发的这些系统都需要陆续的上线,因为临近618有时候也有一些紧急的调整的需要上线,但为了保障线上系统的稳定性是尽可能的减少上线的,也会相应的增强审批力度。就像一级响应、二级响应一样。

而这审批的过程在随着特定时间点会增加不同级别的负责人加入,每个人就像责任链模式中的每一个核心点。对于研发小伙伴并不需要关心具体的审批流程处理细节,只需要知道这个上线更严格,级别也更高,但对于研发人员来说同样是点击相同的提审按钮,等待审核。
实现目标,活动天数不一样经过不一样的人员审批,1天—>运营人员 3天—>运营经理 6天—> 运营总监。具体实现看代码用例!

2.2 场景模式图

下面根据面向对象的思想我们得定义需要用到的对象。我们采用责任链模式和建造者模式来实现审批过程!

2.3 场景代码实现

构建活动请求对象(采用建造者模式)

/*** Description: 构建请求对象* <br/>* Request** @author laiql* @date 2021/11/2 10:23*/
public class Request {/*** 活动id*/private String activityId;/*** 活动名*/private String activityName;/*** 活动开始时间*/private Integer activityTime;/*** 一级审批*/private String levelOne;/*** 二级审批*/private String levelTwo;/*** 三级审批*/private String levelThree;public Request(Builder builder) {super();this.activityId = builder.activityId;this.activityName = builder.activityName;this.activityTime = builder.activityTime;this.levelOne = builder.levelOne;this.levelTwo = builder.levelTwo;this.levelThree = builder.levelThree;}/*** 使用建造者模式*/public static class Builder {public String activityId;public String activityName;public Integer activityTime;public String levelOne;public String levelTwo;public String levelThree;public Builder() {}public Builder setActivityId(String activityId) {this.activityId = activityId;return this;}public Builder setActivityName(String activityName) {this.activityName = activityName;return this;}public Builder setactivityTime(Integer activityTime) {this.activityTime = activityTime;return this;}public Builder setLevelOne(String levelOne) {this.levelOne = levelOne;return this;}public Builder setLevelTwo(String levelTwo) {this.levelTwo = levelTwo;return this;}public Builder setLevelThree(String levelThree) {this.levelThree = levelThree;return this;}public Builder newRequest(Request request) {this.activityId = request.activityId;this.activityName = request.activityName;this.activityTime = request.activityTime;//可以增加参数判断this.levelOne = request.levelOne;this.levelTwo = request.levelTwo;this.levelThree = request.levelThree;return this;}public Request build() {return new Request(this);}}public String activityId() {return activityId;}public String activityName() {return activityName;}public Integer activityTime() {return activityTime;}public String levelOne() {return levelOne;}public String levelTwo() {return levelTwo;}public String levelThree() {return levelThree;}@Overridepublic String toString() {return "Request{" +"activityId='" + activityId + '\'' +", activityName='" + activityName + '\'' +", activityTime=" + activityTime +", levelOne='" + levelOne + '\'' +", levelTwo='" + levelTwo + '\'' +", levelThree='" + levelThree + '\'' +'}';}
}

定义审批结果对象:

/*** Description: 授权结果* <br/>* AuthResult** @author laiql* @date 2021/11/2 10:32*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class AuthResult {private boolean isRatify;private String info;
}

抽象处理请求接口定义:

public interface Ratify {/*** 处理请求** @param chain* @return*/public AuthResult deal(Chain chain);/*** 接口描述:对request和Result封装,用来转发*/interface Chain {/*** 获取当前request请求** @return*/Request request();/*** 转发request请求** @param request* @return*/AuthResult proceed(Request request);}
}

实现Chain的真正的包装Request和转发功能类定义:

public class RealChain implements Ratify.Chain {/*** 具体的请求Request实例*/public Request request;/*** Ratify接口的实现类集合*/public List<Ratify> ratifyList;/*** 已经处理过该request的责任人数量*/private Integer index;public RealChain(Request request, List<Ratify> ratifyList, Integer index) {this.request = request;this.ratifyList = ratifyList;this.index = index;}/*** 返回当前Request对象或者返回当前进行包装后的Request对象** @return*/@Overridepublic Request request() {return request;}/*** 具体转发功能** @param request* @return*/@Overridepublic AuthResult proceed(Request request) {AuthResult proceed = null;if (this.ratifyList.size() > this.index) {RealChain realChain = new RealChain(this.request, this.ratifyList, this.index + 1);Ratify ratify = this.ratifyList.get(this.index);proceed = ratify.deal(realChain);}return proceed;}
}

定义日常活动审批责任类:

@Slf4j
public class DailyAuthHandler implements Ratify {@Overridepublic AuthResult deal(Chain chain) {Request request = chain.request();if (request.activityTime() > 1) {Request newRequest = new Request.Builder().newRequest(request).setLevelOne("1级审批 - " + "运营人员:[张三] - 审批意见:[同意]").build();log.info("活动状态:{}", newRequest.toString());//交给二级人员审批return chain.proceed(newRequest);}return new AuthResult(true, "运营人员:[张三] - 审批意见:[同意]");}
}

定义促销活动审批责任类:

@Slf4j
public class PromotionAuthHandler implements Ratify {@Overridepublic AuthResult deal(Ratify.Chain chain) {Request request = chain.request();if (request.activityTime() > 3) {Request newRequest = new Request.Builder().newRequest(request).setLevelTwo("2级审批 - " + "运营经理:[李四] - 审批意见:[同意]").build();log.info("活动状态:{}", newRequest.toString());//交给三级人员审批return chain.proceed(newRequest);}return new AuthResult(true, "运营经理:[李四] - 审批意见:[同意]");}
}

大促活动审批责任类定有:

@Slf4j
public class Activity618AuthHandler implements Ratify {@Overridepublic AuthResult deal(Ratify.Chain chain) {Request request = chain.request();if (request.activityTime() <= 7) {Request buildRequest = new Request.Builder().newRequest(request).setLevelThree("3级审批 - " + "运营总监:[王五] - 审批意见:[同意]").build();log.info("活动状态:{}", buildRequest.toString());} else {log.info("活动状态:{}", request.toString());return new AuthResult(false, "审批失败!暂时不支持7天以上活动!");}return new AuthResult(true, "运营总监:[王五] - 审批意见:[同意]");}
}

测试用例定义:

    @Testpublic void test() {//构造活动Request request = new Request.Builder().setActivityId("0000000000001").setActivityName("618大促销").setactivityTime(2).build();ChainOfResponsibilityClient chain = new ChainOfResponsibilityClient();AuthResult authResult = chain.execute(request);log.info("执行结果:{}", authResult);}

执行预期结果:

15:49:52.786 [main] INFO com.smartfrank.pattern.example.handler.DailyAuthHandler - 活动状态:Request{activityId='0000000000001', activityName='618大促销', activityTime=6, levelOne='1级审批 - 运营人员:[张三] - 审批意见:[同意]', levelTwo='null', levelThree='null'}
15:49:52.790 [main] INFO com.smartfrank.pattern.example.handler.PromotionAuthHandler - 活动状态:Request{activityId='0000000000001', activityName='618大促销', activityTime=6, levelOne='null', levelTwo='2级审批 - 运营经理:[李四] - 审批意见:[同意]', levelThree='null'}
15:49:52.790 [main] INFO com.smartfrank.pattern.example.handler.Activity618AuthHandler - 活动状态:Request{activityId='0000000000001', activityName='618大促销', activityTime=6, levelOne='null', levelTwo='null', levelThree='3级审批 - 运营总监:[王五] - 审批意见:[同意]'}
15:49:52.790 [main] INFO com.smartfrank.pattern.ChainTest - 执行结果:AuthResult(isRatify=true, info=运营总监:[王五] - 审批意见:[同意])

2.4 优缺点

优点:

  • 降低耦合度,将请求的发送者和接收者解耦。
  • 简化了对象,使得对象不需要知道链的结构。
  • 增强了对象指派职责的灵活性,通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。
  • 增加新的请求处理类很方便。
    缺点:
  • 不能保证请求一定被接收。
  • 系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。
  • 可能不容易观察运行时的特征,有碍于除错。

三、总结

从上面场景案例代码中我们可以体会到,使用了设计模式,代码将变得更加面向对象,符合软件设计原则,同时我们的代码结构变得清晰干净了。
责任链模式很好的处理单一职责和开闭原则,简单了耦合也使对象关系更加清晰,而且外部的调用方并不需要关心责任链是如何进行处理的*(以上程序中可以把责任链的组合进行包装,在提供给外部使用)*。但除了这些优点外也需要是适当的场景才进行使用,避免造成性能以及编排混乱调试测试疏漏问题。

代码地址

手撸设计模式之-责任链模式相关推荐

  1. 乐在其中设计模式(C#) - 责任链模式(Chain of Responsibility Pattern)

    原文:乐在其中设计模式(C#) - 责任链模式(Chain of Responsibility Pattern) [索引页] [源码下载] 乐在其中设计模式(C#) - 责任链模式(Chain of ...

  2. php设计模式之责任链模式

    php设计模式之责任链模式 实际问题 你的论坛有举报功能,版主能解决粗口方面的举报,警察能解决严重一点的黄赌毒方面的举报,更严重的反政府的举报就需要由国安局来完成. 职场中每个人都有直属的上级,如果到 ...

  3. 轻松学习Java设计模式之责任链模式

    我们的态度是:每天进步一点点,理想终会被实现. 前言 设计模式,可能很多人都是看到代码知道怎么回事,但是离开代码再让其说出来,估计就有点含糊其词了,包括我自己在内.Android中其实用到的设计模式也 ...

  4. 走穿java23种设计模式-15责任链模式详解

    走穿java23种设计模式-15责任链模式详解 责任链模式是一种常见的行为模式. 一.责任链模式的现实场景 习伟过生日邀请了很多朋友到KTV一起庆祝,为了增加欢乐的气氛,习伟建议大家一起玩击鼓传花的游 ...

  5. 软件设计模式之责任链模式实验

    软件设计模式之责任链模式实验 一.实验目的 掌握软件责任链模式中的命令模式,能够用责任链模式编写程序,解决实际问题. 二.实验内容与要求 内容:某小学老师指定班里的三位学生收寒假作业,三位学生分别负责 ...

  6. Java设计模式之责任链模式(二)

    所有设计模式传送门 本文将一起介绍学习下设计模式之责任链模式.责任链模式是指使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系.将这些对象连成一条链,并沿着这条链传递该请求,直到有 ...

  7. Java设计模式作业-责任链模式

    Java设计模式作业-责任链模式:Web过滤器 文章目录 前言 一.类图 二.代码及测试结果 1.Trouble类 2.Support类 3.CharSupport类 4.TypeTransformS ...

  8. Java设计模式系列--责任链模式(应用)

    原文网址:Java设计模式系列--责任链模式(应用)_IT利刃出鞘的博客-CSDN博客 简介 说明 本文介绍Java设计模式中的责任链模式的一些使用场景. 责任链模式的好处 符合单一职责原则 每个功能 ...

  9. JAVA设计模式之责任链模式(职责链模式)

    转自JAVA设计模式之责任链模式(职责链模式)​​​​​​​ 责任链/职责链(Chain of Responsibility)模式的定义 为了避免请求发送者与多个请求处理者耦合在一起,将所有请求的处理 ...

最新文章

  1. nanomsg:ZeroMQ作者用C语言新写的消息队列库
  2. C#使用读写锁三行代码简单解决多线程并发写入文件时线程同步的问题
  3. Hadoop 集群的三种方式
  4. python匿名函数里用for_请问这段Python代码如何用匿名函数简化?
  5. jsp页面适应手机屏幕_HTML5之页面缩放 viewport
  6. 生成新的dataframe_Python之Pandas使用系列(九):DataFrame中列操作的技巧
  7. matplotlib中ion()和ioff()的使用
  8. 问答知识图谱还缺少什么信息?
  9. Linux下执行程序出现 Text file busy 提示时的处理方式
  10. 安装树莓派摄像头模块方法
  11. 云计算业务优势扩大,阿里云业务持续高速增长
  12. 怎么知道当前计算机用户名和密码,怎么查看电脑当前所设置的密码
  13. 花三分钟,一起了解一下消费全返模式是怎么样的?消费者又消费又赚钱
  14. 国内十大正规现货交易平台排名(2022最新榜单)
  15. WCF---关于无法使用以下搜索标准找到 X.509 证书的问题
  16. Gvim开发环境配置笔记--Windows篇(转)
  17. 微信小程序 如何接入视频激励广告
  18. Mars3D中无人机航拍的数据想叠加到三维地图上,实现的流程和方法
  19. 服务器端性能的关键指标,应用服务器性能评价关键指标
  20. 架设win2003r2下配置好iis6+php+mysql_PHP环境搭建之Windows 2003 IIS6+PHP5+MySQL5+Zend图文教程 | 沉默过客...

热门文章

  1. scala的futue和promise
  2. 【java】序列化与反序列
  3. 【解决方案】EasyNVR海量安防设备接入实时直播+云端(服务器)录像的实现
  4. 谁小时候没有计算机课,你的童年电脑记忆里有它们吗?
  5. Gym - 101128H - Sheldon Numbers
  6. WORD如何设置打印? 三分钟学会WORD打印技巧
  7. Redisson 锁
  8. C语言*p、p以及p的区别
  9. 计算机图形学上机实验一-画出一个钻石
  10. CAD随机孔隙3D插件 孔隙结构 多孔结构模型