责任链模式的应用场景
- 格式:docx
- 大小:3.66 KB
- 文档页数:2
通俗易懂设计模式解析——责任链模式前言今天我们介绍的是责任链模式【Chain of Responsibility Pattern】。
对于责任链模式理解起来还是比较容易的。
例如在公司请假、三天以内部门经理批准即可,但是三到七天可能就需要总监批准了、七天以上需要副总裁批准。
对于这么一个需求最初的解决方案就是if-else语句判断。
但是一旦请假的模式增加一种则需要对多重if-else进行修改,这就违背了开闭原则。
这个时候就可以采用责任链模式来解决其问题。
责任链模式为请求创建一个接收者对象的链。
这种模式给予请求的类型,对请求的发送者和接收者进行解耦。
责任链模式介绍一、来由在软件系统中,经常会有一个请求可能会被多个对象处理。
但是每一次都是被一个对象处理。
又不能确定是哪一个对象。
如果显示指定每一个对象。
会对请求发送者和接收者造成紧耦合。
那么如何做到对请求的发送者和接收者进行解耦。
并且在运行时自行决定处理请求的对象呢?二、意图避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。
三、案例四、责任链模式代码示例看上述案例图,主要涉及到两个部分:抽象处理者:定义一个处理请求的接口具体处理者:实现处理请求的接口、可以选择是自己处理或者传递给下一个接收者。
包含对下一个接收处理者的引用。
责任链模式的组成部分还是比较简单的。
我们看这么一个案例,还是用户结算时金额计算的案例。
根据用户的会员等级进行对应的折扣结算。
普通用户全额计算、普通会员95折计算、黄金会员9折计算、钻石会员7折计算:我们首先看看不使用责任链模式如何处理:namespace ChainofResponsibility_Pattern{class Program{ static void Main(string[] args){decimal Money =200M;var memberType = MemberType.GoldMember;//普通会员,95折计算if (memberType == MemberType.Member){Console.WriteLine($"普通会员,95折计算,最后金额为{Money * 0.95M}");}//黄金会员,9折计算else if(memberType == MemberType.GoldMember){Console.WriteLine($"黄金会员,9折计算,最后金额为{Money * 0.9M}");}//钻石会员,7折计算else if(memberType == MemberType.DiamondsMember){Console.WriteLine($"钻石会员,7折计算,最后金额为{Money * 0.7M}");}//无会员,全额计算else{Console.WriteLine($"无会员,全额计算,最后金额为{Money}");}}public enum MemberType{[Description("无会员")]NoMember = 1,[Description("普通会员")]Member = 2,[Description("黄金会员")]GoldMember = 3,[Description("钻石会员")]DiamondsMember = 4}}}这里我们可以看到我们使用了多个if条件判断完成的此需求(或者switch语句)。
c语言责任链模式-回复责任链模式是一种行为设计模式,用于将请求从一个对象传递到另一个对象,直到请求被处理或达到处理器链的末尾。
在这个模式中,请求沿着一系列互相关联的处理器对象链传递,每个处理器对象都有机会处理请求或将其传递给下一个处理器对象。
在实际应用中,责任链模式可以用于许多场景,例如日志记录、权限验证、异常处理等。
在本文中,我们将以权限验证为例,一步一步地介绍责任链模式的原理、结构和实现方法。
1. 原理:责任链模式由一系列的处理器对象组成,每个处理器对象都有自己的职责和处理逻辑。
当一个请求到达时,责任链的头部处理器开始处理请求,如果可以处理该请求,则处理请求并结束。
如果无法处理该请求,则将其传递给责任链中的下一个处理器对象,直到请求被处理或者到达责任链的末尾。
2. 结构:责任链模式包含以下几个角色:- Handler(处理器):定义处理请求的接口,并保持对下一个处理器的引用。
- ConcreteHandler(具体处理器):实现处理请求的逻辑,并根据需要决定是否将请求传递给下一个处理器。
- Client(客户端):创建处理器链,将请求传递给链的头部处理器开始处理。
3. 实现:我们以权限验证为例,来演示如何使用责任链模式。
首先,我们定义一个处理器接口Handler,它包含处理请求的方法handleRequest()和设置下一个处理器的方法setNextHandler()。
然后,我们创建两个具体处理器AdminHandler和UserHandler,它们分别实现了Handler接口。
AdminHandler负责验证管理员权限,如果请求是管理员权限,就处理请求,否则将其传递给下一个处理器。
UserHandler 处理普通用户的请求。
接下来,我们在Client中创建处理器链,并将请求传递给链的头部处理器。
每个处理器在处理请求时,都可以决定是否将请求传递给下一个处理器。
以下是代码示例:定义处理器接口interface Handler {void handleRequest(Request request);void setNextHandler(Handler nextHandler);}具体处理器实现class AdminHandler implements Handler {private Handler nextHandler;public void handleRequest(Request request) {if (request.getPermission().equals("admin")) {处理请求System.out.println("Admin handled the request.");} else {传递给下一个处理器nextHandler.handleRequest(request);}}public void setNextHandler(Handler nextHandler) { this.nextHandler = nextHandler;}}class UserHandler implements Handler {private Handler nextHandler;public void handleRequest(Request request) {if (request.getPermission().equals("user")) {处理请求System.out.println("User handled the request.");} else {传递给下一个处理器nextHandler.handleRequest(request);}}public void setNextHandler(Handler nextHandler) { this.nextHandler = nextHandler;}}定义请求类class Request {private String permission;public Request(String permission) {this.permission = permission;}public String getPermission() {return permission;}}客户端代码public class Client {public static void main(String[] args) {创建处理器对象Handler adminHandler = new AdminHandler();Handler userHandler = new UserHandler();设置处理器链adminHandler.setNextHandler(userHandler);创建请求Request request1 = new Request("admin");Request request2 = new Request("user");发起请求adminHandler.handleRequest(request1); Output: Admin handled the request.adminHandler.handleRequest(request2); Output: User handled the request.}}通过运行上述代码,我们可以看到,当请求的权限是"admin"时,会由AdminHandler处理;当请求的权限是"user"时,会由UserHandler处理。
php设计模式之责任链模式php设计模式之责任链模式实际问题你的论坛有举报功能,版主能解决粗⼝⽅⾯的举报,警察能解决严重⼀点的黄赌毒⽅⾯的举报,更严重的反政府的举报就需要由国安局来完成。
职场中每个⼈都有直属的上级,如果到达⾃⼰的问题⾃⼰能够处理,就⾃⼰处理,否则交给上级。
这⾥相当于警察是版主的上级,国安是警察的上级。
简介职责链模式(⼜叫责任链模式)包含了⼀些命令对象和⼀些处理对象,每个处理对象决定它能处理那些命令对象,它也知道应该把⾃⼰不能处理的命令对象交下⼀个处理对象,该模式还描述了往该链添加新的处理对象的⽅法。
职场中每个⼈都有直属的上级,如果到达⾃⼰的问题⾃⼰能够处理,就⾃⼰处理,否则交给上级。
当⼀个问题来到的时候,将这个问题交给最低级的处理者,能处理就处理,不能处理就往上⾯传。
每个管理者都有指向上级的⼀个指针。
类图⾓⾊:抽象处理者(Manager):定义出⼀个处理请求的接⼝。
如果需要,接⼝可以定义出⼀个⽅法,以设定和返回对下家的引⽤。
这个⾓⾊通常由⼀个抽象类或接⼝实现。
具体处理者(CommonManager):具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。
由于具体处理者持有对下家的引⽤,因此,如果需要,具体处理者可以访问下家。
代码1 <?php2/**3 * Created by PhpStorm.4 * User: Jang5 * Date: 2015/6/116 * Time: 10:167*/89//申请Model10class Request11 {12//数量13public$num;14//申请类型15public$requestType;16//申请内容17public$requestContent;18 }1920//抽象管理者21abstract class Manager22 {23protected$name;24//管理者上级25protected$manager;26public function __construct($_name)27 {28$this->name = $_name;29 }3031//设置管理者上级32public function SetHeader(Manager $_mana)33 {34$this->manager = $_mana;35 }3637//申请请求38abstract public function Apply(Request $_req);3940 }4142//经理43class CommonManager extends Manager44 {45public function __construct($_name)46 {47 parent::__construct($_name);48 }49public function Apply(Request $_req)50 {51if($_req->requestType=="请假" && $_req->num<=2)52 {53echo "{$this->name}:{$_req->requestContent} 数量{$_req->num}被批准。
责任链模式和观察者模式责任链模式顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了⼀个接收者对象的链。
这种模式给予请求的类型,对请求的发送者和接收者进⾏解耦。
这种类型的设计模式属于⾏为型模式。
这种模式中,通常每个接收者都包含对另⼀个接收者的调⽤。
如果⼀个对象不能处理请求,那么它会把相同的请求传给下⼀个接收者,以此类推。
介绍意图:避免请求发送者和接收者耦合在⼀起,让多个对象都有可能接收请求,将这些对象连接成⼀条链,并且沿着这条链传递请求,直到有对象处理他为⽌。
主要解决:职责链上处理者负责处理请求,客户只需要将请求发送到职责链上即可,⽆须关⼼请求的处理细节和请求的传递,所以职责链中请求的发送者和处理者解耦了。
何时使⽤:在处理消息的时候以过滤很多道。
如何解决:拦截的类都实现统⼀接⼝。
应⽤实例: 1、红楼梦中的"击⿎传花"。
2、JS 中的事件冒泡。
3、JAVA WEB 中 Apache Tomcat 对 Encoding 的处理,Struts2 的拦截器,jsp servlet 的 Filter。
优点: 1、降低耦合度。
它将请求的发送者和接收者解耦。
2、简化了对象。
使得对象不需要知道链的结构。
3、增强给对象指派职责的灵活性。
通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。
4、增加新的请求处理类很⽅便。
缺点: 1、不能保证请求⼀定被接收。
2、系统性能将受到⼀定影响,⽽且在进⾏代码调试时不太⽅便,可能会造成循环调⽤。
3、可能不容易观察运⾏时的特征,有碍于除错。
使⽤场景: 1、有多个对象可以处理同⼀个请求,具体哪个对象处理该请求由运⾏时刻⾃动确定。
2、在不明确指定接收者的情况下,向多个对象中的⼀个提交⼀个请求。
3、可动态指定⼀组对象处理请求。
注意事项:在 JAVA WEB 中遇到很多应⽤。
观察者模式当对象间存在⼀对多关系时,则使⽤观察者模式(Observer Pattern)。
责任链模式的具体应⽤1.业务场景⽣产车间中使⽤的条码扫描,往往⼀把扫描枪需要扫描不同的条码来处理不同的业务逻辑,⽐如,扫描投⼊料⼯位条码、扫描投⼊料条码、扫描产出⼯装条码等,每种类型的条码位数是不⼀样,因此通过条码长度来进⾏业务区分。
2.初步设计⾯对此场景,能够想到的最简单的设计就是使⽤if...else if...或者swith进⾏判断,因此,我们编写的代码如下1switch(barCode.length)2 {3case3:4 DoSomething1();5break;6case4:7 DoSomething2();8break;9case5:10 DoSomething3();11break;12default:13 DoSomething4();14break;15 }使⽤是if...else if...或者switch已经基本上满⾜了需求,以后需要添加扫描场景,只需要增加判断,完成对应的⽅法即可。
作为⼀个程序员,仅仅满⾜需求的话,往往降低了对⾃⼰的要求,同时,随着扫描业务的增加,switch中的代码逐渐增加,多到我们⾃⼰都觉得这段代码读起来就像是吃着前天剩下的硬馒头⼀样,难以下咽。
3.设计提升上述场景完全可以使⽤设计模式中的责任链模式来进⾏优化,实施步骤如下:3.1 定义处理结果⼀个处理在责任链上流动时,有两种结果,⼀是不能处理,转给其后继者,⼆是可以处理,同时⼜引出两种结果,处理成功和处理失败。
因此,对处理结果统⼀定义为枚举类型1public enum HandleResult2 {3 ///<summary>4///成功5///</summary>6 Success=0,7///<summary>8///失败9///</summary>10 Failed = 1,11///<summary>12///未处理13///</summary>14 Unhandle = 215 }3.2定义业务抽象类AbstractBarCodeHandler定义业务抽象类,包含⼀个属性“Successor”,⽤于标记其后继者,⼀个公共⽅法“HandleRequest”,当调⽤真正的业务处理⽅法时返回未处理,则调⽤其后继者进⾏处理,⼀个抽象⽅法“HandleRequestCore”,每个扫描业务具体类,需要实现此⽅法,并对条码进⾏处理。
设计模式之责任链模式责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它将请求的发送者和接受者解耦,并且允许多个对象都有机会处理这个请求。
责任链模式通常被用于处理对象间的请求传递,使得每个对象都有机会处理请求,同时避免请求的发送者和接受者之间的耦合关系。
责任链模式由一系列的处理对象组成,每个处理对象都负责处理特定的请求,并且对下一个处理对象的引用。
当一个请求被发送时,责任链上的每个处理对象依次判断是否能处理该请求,如果能则立即处理,如果不能则传递给下一个处理对象。
这样,请求发送者并不需要知道请求最终会被哪个对象处理。
责任链模式的结构包括以下几个角色:1. 抽象处理者(Handler):定义处理请求的接口,通常包含一个指向下一个处理者的引用。
2. 具体处理者(ConcreteHandler):实现抽象处理者的接口,具体处理请求的逻辑,并且可根据需要传递请求给下一个处理者。
下面通过一个实际的例子来说明责任链模式的应用。
假如在一个电商系统中,有三个订单处理的环节:商品审核、支付检查和库存验证。
货物在途过程中,可能会出现商品信息不完整、支付异常或库存不足的情况。
我们可以使用责任链模式来设计这样一个订单处理系统。
首先,定义一个抽象处理者(Handler)接口,包含一个处理请求的方法,并且可以设置下一个处理者的引用。
```javapublic interface Handler {void setNextHandler(Handler handler);void handleRequest(Order order);}```然后,实现具体的处理者(ConcreteHandler)类,包括商品审核处理者、支付检查处理者和库存验证处理者。
每个具体处理者都实现了处理请求的方法,并且根据需要判断是否需要传递请求给下一个处理者。
```javapublic class ProductCheckHandler implements Handler {private Handler nextHandler;@Overridepublic void setNextHandler(Handler handler) {this.nextHandler = handler;}@Overridepublic void handleRequest(Order order) {// 商品审核逻辑// ...// 如果有下一个处理者,则传递请求if (nextHandler != null) {nextHandler.handleRequest(order);}}}public class PaymentCheckHandler implements Handler { private Handler nextHandler;@Overridepublic void setNextHandler(Handler handler) {this.nextHandler = handler;}@Overridepublic void handleRequest(Order order) {// 支付检查逻辑// ...// 如果有下一个处理者,则传递请求if (nextHandler != null) {nextHandler.handleRequest(order);}}}public class StockCheckHandler implements Handler { private Handler nextHandler;@Overridepublic void setNextHandler(Handler handler) {this.nextHandler = handler;}@Overridepublic void handleRequest(Order order) {// 库存验证逻辑// ...// 如果有下一个处理者,则传递请求if (nextHandler != null) {nextHandler.handleRequest(order);}}}```最后,在客户端代码中组装责任链,并将请求发送给第一个处理者。
责任链模式选择题
1. 什么是责任链模式?
A. 是一种设计模式,用于处理请求链中的多个处理程序
B. 是一种编程语言,用于编写可重用的软件组件
C. 是一种网络协议,用于实现互联网连接
2. 责任链模式的主要优点是什么?
A. 提高代码的可读性和可维护性
B. 减少代码量并简化编程过程
C. 提高系统的可扩展性和灵活性
3. 在责任链模式中,通常会有一个处理程序链,以下哪个描述是正确的?
A. 处理程序链中的每个处理程序都独立处理请求
B. 处理程序链中的每个处理程序都只能处理特定类型的请求
C. 处理程序链中的每个处理程序都按照顺序处理请求,并将结果传递给下一个处理程序
4. 在责任链模式中,如何处理无法处理的请求?
A. 直接忽略无法处理的请求
B. 将无法处理的请求传递给链中的下一个处理程序
C. 将无法处理的请求传递给调用者,由调用者决定如何处理
5. 以下哪个不是责任链模式的应用场景?
A. Web开发中的请求处理
B. 数据库查询优化
C. 分布式系统中的服务调用
6. 在责任链模式中,通常哪个类会处理请求?
A. 链中的第一个节点
B. 链中的最后一个节点
C. 链中的任意一个节点
D. 链中的指定节点
7. 责任链模式主要应用于哪些场景?
A. 单个请求需要被多个处理者处理的情况
B. 多个请求需要被单个处理者处理的情况
C. 需要对请求进行过滤或转换的情况
D. 需要对请求进行路由或分发的情况
8. 在责任链模式中,通常使用什么方法来传递请求?
A. 直接调用
B. 事件驱动
C. 回调函数
D. 信号量。
C#设计模式(21)——责任链模式⼀、引⾔ 在现实⽣活中,有很多请求并不是⼀个⼈说了就算的,例如⾯试时的⼯资,低于1万的薪⽔可能技术经理就可以决定了,但是1万~1万5的薪⽔可能技术经理就没这个权利批准,可能就需要请求技术总监的批准,所以在⾯试的完后,经常会有⾯试官说,你这个薪⽔我这边觉得你这技术可以拿这个薪⽔的,但是还需要技术总监的批准等的话。
这个例⼦也就诠释了本⽂要介绍的内容。
⽣活中的这个例⼦真是应⽤了责任链模式。
2.1 责任链模式的定义 从⽣活中的例⼦可以发现,某个请求可能需要⼏个⼈的审批,即使技术经理审批完了,还需要上⼀级的审批。
这样的例⼦,还有公司中的请假,少于3天的,直属Leader就可以批准,3天到7天之内就需要项⽬经理批准,多余7天的就需要技术总监的批准了。
介绍了这么多⽣活中责任链模式的例⼦的,下⾯具体给出⾯向对象中责任链模式的定义。
责任链模式指的是——某个请求需要多个对象进⾏处理,从⽽避免请求的发送者和接收之间的耦合关系。
将这些对象连成⼀条链⼦,并沿着这条链⼦传递该请求,直到有对象处理它为⽌。
2.2 从责任链模式的定义可以发现,责任链模式涉及的对象只有处理者⾓⾊,但由于有多个处理者,它们具有共同的处理请求的⽅法,所以这⾥抽象出⼀个抽象处理者⾓⾊进⾏代码复⽤。
这样分析下来,责任链模式的结构图也就不⾔⽽喻了,具体结构图如下所⽰。
主要涉及两个⾓⾊:抽象处理者⾓⾊(Handler):定义出⼀个处理请求的接⼝。
这个接⼝通常由接⼝或抽象类来实现。
具体处理者⾓⾊(ConcreteHandler):具体处理者接受到请求后,可以选择将该请求处理掉,或者将请求传给下⼀个处理者。
因此,每个具体处理者需要保存下⼀个处理者的引⽤,以便把请求传递下去。
2.3 责任链模式的实现 有了上⾯的介绍,下⾯以公司采购东西为例⼦来实现责任链模式。
公司规定,采购架构总价在1万之内,经理级别的⼈批准即可,总价⼤于1万⼩于2万5的则还需要副总进⾏批准,总价⼤于2万5⼩于10万的需要还需要总经理批准,⽽⼤于总价⼤于10万的则需要组织⼀个会议进⾏讨论。
⼯⼚模式、策略者模式、责任链模式综合应⽤设计模式的具体运⽤: 简单⼯⼚模式、策略者模式、责任链模式定义与使⽤classLoader的具体运⽤ ⾃定义的classloader 来动态加载类程序功能设计: 在商城购物时,商城可能会在特殊的⽇⼦、或者依据会员等级,对结算的商品进⾏价格上的优惠,本篇将模拟价格计算时,优惠策略的动态选择和优惠策略的链式处理;程序流程图: 图中有两种价格优惠计算的流程图: 流程2:价格优惠计算时直接采⽤责任链模式进⾏处理,设计和流程都⽐较简单,作者更倾向于这种流程设计;但为了练习和使⽤更多的设计模式,所以本篇采⽤了流程2的⽅法实现; 流程1:将价格优惠计算分成了特殊和固定价格优惠(⽐如:会员值。
或则满额减等),这种流程模式在进⼊到特殊优惠条件时,可以采⽤责任链的⽅式实现,⽽固定价格优惠计算时,可以采⽤策略者模式进⾏实现;UML 图:源码: 定义价格策略接⼝/*** 商品价格的计算策略*/public interface PriceStrategy {double calcPrice(double price);} 定义⼀个注解,⽤于⼯⼚动态加载和创建PriceStrategy(价格策略)对象import ng.annotation.Documented;import ng.annotation.ElementType;import ng.annotation.Retention;import ng.annotation.RetentionPolicy;import ng.annotation.Target;@Documented@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)public @interface FixedPrivilegePrice {double max() default 0;double min() default Integer.MAX_VALUE;} 两个简单的价格策略算法的实现,这⾥利⽤注解的两个属性:min 和 max 属性,定义策略类的使⽤要求:即计算的价格必须在指定的价格区间内@FixedPrivilegePrice(min=100,max=500)public class SimpleStrategy1 implements PriceStrategy {@Overridepublic double calcPrice(double price) {return price * 0.8;}}@FixedPrivilegePrice(min=500,max=Integer.MAX_VALUE)public class SimpleStrategy2 implements PriceStrategy {@Overridepublic double calcPrice(double price) {return price * 0.7;}}默认的价格优惠策略类,⽤于⽆可⽤策略时,将不对价格进⾏优惠public class DefaultPriceStrategy implements PriceStrategy {@Overridepublic double calcPrice(double price) {return price;}}定义特殊价格的优惠策略接⼝,⽤于特殊价格优惠策略的链式处理;next() ⽅法在这⾥是责任链模式实现的关键;/*** ⽤于价格计算时,提供特殊的价格优惠算法**/public interface PricePrivilege extends PriceStrategy {PricePrivilege next();void register(PricePrivilege pp);}抽象类,实现对象链的选择和注册;public abstract class AbstractPricePrivilege implements PricePrivilege {protected PricePrivilege next;public PricePrivilege next() {return next;}public void register(PricePrivilege pp) {next = pp;}}特殊价格优惠策略两个简单实现:public class Birthday extends AbstractPricePrivilege {@Overridepublic double calcPrice(double price) {//会员⽣⽇⼀律9折优惠return price * 0.9;}}public class PreferentialCar extends AbstractPricePrivilege {@Overridepublic double calcPrice(double price) {// 这是⼀张满100百减10的优惠卡if(price >= 100)price -= 10;return price;}}PricePrivilege 的⼯⼚接⼝public interface IPriceStratedyFactory {PriceStrategy createAndGet(double price);}PricePrivilege 的⼯⼚实现,这个⼯⼚类是动态加载和动态选择策略的核⼼: 1, 动态加载策略:该⼯⼚将从给定的⼀个⽬录中,动态加载可⽤的所有策略,并将这些策略保存到⼀个链表中;(并且可以提供⼀个动态添加和删除策略的接⼝,或者在从给定⽬录中动态加载策略时,启动⼀个定时检查器,⽤于间断性添加和删需要考虑策略的实效性;———————————— 后续思想,本篇未实现;) 2,动态策略选择:每⼀个策略类都使⽤了FixedPrivilegePrice 这个注解,本篇该注解使⽤了两个属性:min 和max ,表⽰价格的最⼤值和最⼩值,当结算价格在这个区间时,就选择这种策略;当然这只是简单的价格判断,也可以根据实际添加import java.io.File;import java.io.FilenameFilter;import .URL;import java.util.HashSet;public class PriceStrategyFactory implements IPriceStratedyFactory {public PriceStrategy createAndGet(double price) {PriceStrategy ps = findPriceStrategyInHolder(price);if(ps == null) {ps = PriceStrategyHolder.DEFAULT_PRICE_STRATEGY;}return ps;}private PriceStrategy findPriceStrategyInHolder(double price) {for(PriceStrategy ps : PriceStrategyHolder.priceStrategy) {FixedPrivilegePrice fpp = ps.getClass().getAnnotation(FixedPrivilegePrice.class);if(matchCondition(price ,fpp))return ps;}return null;}private boolean matchCondition(double price ,FixedPrivilegePrice fpp) {return price >= fpp.min() && price <= fpp.max();}static private class PriceStrategyHolder {static private final PriceStrategy DEFAULT_PRICE_STRATEGY = new DefaultPriceStrategy();static private HashSet<PriceStrategy> priceStrategy = new HashSet<>();static final private LoadPriceStrategyUtil LOAD_UTIL = new LoadPriceStrategyUtil();static {LOAD_UTIL.classLoder(priceStrategy);}}static private class LoadPriceStrategyUtil{static final private String STRATEGY_URL = "learn.design.model.demo1";void classLoder(HashSet<PriceStrategy> pss) {String[] classFiles = findClassFileFromPath();if(classFiles == null) return;DynamicLoaderClass dlc = new DynamicLoaderClass();for(String classFileName : classFiles) {try {String className = generateClassName(classFileName);Class<?> cls = dlc.loadClass(className);FixedPrivilegePrice fpp = cls.getAnnotation(FixedPrivilegePrice.class);if(fpp != null ) {pss.add((PriceStrategy) cls.newInstance());}} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e1) {}}}String generateClassName(String classFileName) {return STRATEGY_URL + "." + classFileName.substring(0 ,classFileName.indexOf("."));}String[] findClassFileFromPath() {//符号替换String loaderUrl = STRATEGY_URL.replace(".", "/");URL url = ClassLoader.getSystemResource(loaderUrl);if(url == null)return null;return new File(url.getPath()).list(new FilenameFilter() {@Overridepublic boolean accept(File dir, String name) {return name.endsWith(".class");}});}}}提供⼀个⾃定义的类加载器⼯具,⽤于动态的加载给定⽬录下的class⽂件,默认从项⽬的classpath路径下查找;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;public class DynamicLoaderClass extends ClassLoader {private String path;public DynamicLoaderClass(){this(Thread.currentThread().getContextClassLoader().getResource("").getPath());}public DynamicLoaderClass(String path) {this.path = path;}@Overridepublic Class<?> loadClass(String className) throws ClassNotFoundException {Class<?> cls = loadClassByParent(className);if(cls == null)cls = loadClassBySelf(className);return cls;}private Class<?> loadClassBySelf(String className) throws ClassNotFoundException {return findClass(className);}private Class<?> loadClassByParent(String className){Class<?> cls = null;try{cls = super.loadClass(className);}catch (ClassNotFoundException e) {//load class failed;}return cls;}@Overrideprotected Class<?> findClass(String className) throws ClassNotFoundException {byte[] b = getResourceForCurrentPath(className);return defineClass(className, b, 0, b.length);}private byte[] getResourceForCurrentPath(String className) throws ClassNotFoundException{return getResourceForPath(genrateResourcePath(className));}private byte[] getResourceForPath(String resourcePath) throws ClassNotFoundException {checkResourceIsExist(resourcePath);return readResource(resourcePath);}private byte[] readResource(String resourcePath) throws ClassNotFoundException {byte[] result = null;File file = new File(resourcePath);FileInputStream fis = null;try {fis = new FileInputStream(file);result = new byte[fis.available()];fis.read(result);fis.close();} catch (FileNotFoundException e) {// This should only happen with multithreading} catch (IOException e) {throw new ClassNotFoundException();}return result;}private void checkResourceIsExist(String resourcePath) throws ClassNotFoundException {File file = new File(resourcePath);if(!file.exists())throw new ClassNotFoundException();}private String genrateResourcePath(String className){return path + "/" + className.replace(".", "/") +".class";}}价格处理者接⼝,接⼝规定:价格的最终结算价格将在这个接⼝中处理完成;⽤户不需要关⼼如何完成,以及是否使⽤了价格的策略,相当于将所有的价格优惠策略都封装和隐藏起来,实现与客户端的分离/*** 提供对商品价格的计算⽅式**/public interface PriceHandler {double calcPrice(double price ,PricePrivilege pp);}定义⼀个书记类型商品的价格处理器, 1,该类将从⽤户那⾥获取⽤户可以使⽤的特殊优惠策略,本篇中直接传⼊了特殊优惠策略的对象,这⾥是可以改进的:传⼊特殊优惠策略的满⾜条件,⽐如:⽤户领取了⼀张优惠卡,就传⼊该优惠卡的标识即可; 2,该类依赖⼀个与⼀个价格策略的⼯⼚接⼝,该类将通过该⼯⼚接⼝动态的选择⼀个策略;public class BookPriceHandler implements PriceHandler{private IPriceStratedyFactory ipsf;public BookPriceHandler() {this(new PriceStrategyFactory());}public BookPriceHandler(IPriceStratedyFactory ipsf) {this.ipsf = ipsf;}@Overridepublic double calcPrice(double price, PricePrivilege pp) {//特权价格price = privilegePrice(price, pp);//固定策略price = ipsf.createAndGet(price).calcPrice(price);return price;}private double privilegePrice(double price , PricePrivilege pp) {if(pp == null) return price;return privilegePrice(pp.calcPrice(price), pp.next());}}demo:public class Demo {public static void main(String[] args) {BookPriceHandler bphandler = new BookPriceHandler();PricePrivilege pc = new PreferentialCar();PricePrivilege b = new Birthday();b.register(pc);double price = bphandler.calcPrice(500, b);System.out.println(price);}}使⽤注意:请将策略类放置与PriceStrategyFactory $LoadPriceStrategyUtil.STRATEGY_URL所指定的包路径下,否则将抛出classnotfound 异常;。
责任链模式的应用场景责任链模式是一种行为设计模式,它允许多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。
在责任链模式中,请求沿着一个链传递,直到有一个对象能够处理它为止。
责任链模式的应用场景很广泛,下面将介绍一些常见的应用场景。
1. 用户认证和授权在一个系统中,用户的请求可能需要经过多个环节的认证和授权才能被处理。
使用责任链模式,可以将这些环节抽象成一个个的处理器,并按照认证和授权的顺序组成一个责任链。
当用户发送请求时,责任链中的处理器依次进行认证和授权操作,直到有一个处理器能够处理该请求或者整个责任链结束。
2. 日志记录在一个系统中,需要对某些操作进行日志记录,以便后续的审计和问题排查。
使用责任链模式,可以将日志记录的逻辑封装到多个处理器中,并按照一定的顺序组成一个责任链。
当需要记录日志时,请求会沿着责任链传递,每个处理器都可以选择是否记录日志,以及记录日志的方式和内容。
3. 异常处理在一个系统中,可能会出现各种各样的异常情况,需要对这些异常进行处理。
使用责任链模式,可以将不同类型的异常处理逻辑分别封装到不同的处理器中,并按照一定的顺序组成一个责任链。
当系统出现异常时,请求会沿着责任链传递,每个处理器都可以选择是否处理该异常,以及如何处理。
4. 数据校验在一个系统中,用户输入的数据需要进行校验,以确保数据的有效性和合法性。
使用责任链模式,可以将不同类型的校验逻辑封装到不同的处理器中,并按照一定的顺序组成一个责任链。
当用户输入数据时,请求会沿着责任链传递,每个处理器都可以选择是否校验该数据,以及如何校验。
5. 请求过滤在一个系统中,可能需要对请求进行过滤,以确保请求的合法性和安全性。
使用责任链模式,可以将不同类型的过滤逻辑封装到不同的处理器中,并按照一定的顺序组成一个责任链。
当请求到达时,请求会沿着责任链传递,每个处理器都可以选择是否过滤该请求,以及如何过滤。
以上是责任链模式的一些常见应用场景,通过使用责任链模式,可以将复杂的处理逻辑分解成多个简单的处理器,使系统更加灵活和可扩展。
设计模式--责任链模式简介责任链模式(Chain of Responsibility Pattern)也叫职责链模式:是将链中每⼀个节点看作是⼀个对象,每个节点处理的请求均不同,且内部⾃动维护⼀个下⼀节点对象。
当⼀个请求从链式的⾸端发出时,会沿着链的路径依次传递给每⼀个节点对象,知道有对象处理这个请求为⽌。
属于⾏为型模式。
责任链的应⽤场景1、⼯作中的审批流程2、游戏中的闯关责任链模式主要是解耦了请求与处理,客户只需将请求发送到链上即可,⽆需关⼼请求的具体内容和处理细节,请求会⾃动进⾏传递直⾄有节点对象进⾏处理。
适⽤于以下应⽤场景:1、多个对象可以处理同⼀请求,但具体由哪个对象处理则在运⾏时动态决定;2、在不明确指定接受者的情况下,向多个对象中的⼀个提交⼀个请求3、可动态指定⼀组对象处理请求责任链模式的UML类图:从UML类图,我们可以看到,责任链模式只要包含两种⾓⾊:抽象处理者(Handler):定义⼀个请求处理的⽅法,并维护⼀个下⼀个处理节点Handler对象的引⽤;具体处理者(ConcreteHandler):对请求进⾏处理,如果不感兴趣,则进⾏转发。
责任链模式的本质是解耦请求与处理,让请求在处理链中能进⾏传递与被处理;理解责任链模式应当理解的是其模式⽽不是具体实现,责任链模式的独到之处是其将节点处理者组成了链式结构,并允许节点⾃⾝决定是否进⾏请求处理或转发,相当于让请求流动了起来。
责任链模式在源码中的体现1、JDK中的应⽤,Filter类public interface Filter {public default void init(FilterConfig filterConfig) throws ServletException {}public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException;public default void destroy() {}}这个接⼝相当于责任链模型中的Handler抽象⾓⾊。
风控规则责任链模式-概述说明以及解释1.引言1.1 概述在金融、互联网等行业中,风控规则是保障业务安全和风险控制的关键环节。
风控规则用于检测、判断和控制不符合规定的行为和交易,以保护公司和用户的利益。
然而,随着业务的不断扩展和复杂化,单一的风控规则已经无法满足多样化的业务需求。
责任链模式是一种能够解决复杂业务需求的设计模式。
它通过将请求与处理逻辑解耦,形成一个责任链条,每个处理节点都可以根据需求进行处理或者转发请求,从而满足不同的业务规则。
责任链模式可以提高系统的灵活性和可扩展性,使得处理逻辑更加清晰和易于维护。
风控规则责任链模式将风控规则与责任链模式相结合,以应对复杂多变的业务风险和需求。
通过将不同的风控规则按照一定的顺序组织成责任链条,可以逐个处理和判断不符合规定的行为和交易。
当一个规则节点无法处理时,将请求转发给责任链上的下一个节点,直到找到能够处理该请求的节点为止。
这种方式可以使得系统更加灵活和高效,能够快速响应不同的业务需求和风险情况。
本文将深入探讨风控规则责任链模式的定义、原理、实现方式,以及其在实际应用中的优点和应用案例。
通过对该模式的研究,我们可以更好地理解和应用风控规则责任链模式,提升系统的风险控制能力,保护业务的安全和稳定。
文章结构部分的内容可以写成以下形式:1.2 文章结构本文主要包括以下几个部分:2. 正文部分:介绍风控规则责任链模式的相关概念、定义、作用以及实际应用。
2.1 风控规则:首先,会对风控规则进行详细的定义,并探讨其在金融、互联网等领域中的作用。
此外,还会探讨不同场景下的风控规则应用。
2.2 责任链模式:接着,我们将介绍责任链模式的定义以及其在软件设计中的原理。
同时,还会对责任链模式的常见实现方式进行讨论。
2.3 风控规则责任链模式:最后,我们将深入研究风控规则责任链模式的概述,包括其优点和应用案例。
我们将探讨该模式在风控规则中的具体应用,并详细讲解其在实际项目中的实施方式。
面向对象程序设计中的责任链模式应用责任链模式是面向对象程序设计中常用的一种设计模式,其主要作用是将请求对象沿着一个由多个对象组成的处理链传递,直到最终被处理。
在这个过程中,每个对象都承担着一定的责任,只要能够处理该请求,就会进行处理,否则就会将请求交给下一个处理对象,直到找到处理该请求的对象为止。
本文将介绍该模式的应用。
一、责任链模式的结构责任链模式由三部分构成,分别是抽象处理者(Handler)、具体处理者(Concrete Handler)和客户端(Client)。
1. 抽象处理者(Handler)抽象处理者是责任链中的核心元素,它定义了所有具体处理者共有的接口和抽象方法。
它通常包括一个指向下一个处理者的引用,以及处理请求的方法。
抽象处理者的实现类可以拒绝处理请求,也可以转移请求给下一个处理者。
抽象处理者的结构如下所示:public abstract class Handler {protected Handler successor;//下一个处理者public void setSuccessor(Handler successor) {//设置下一个处理者this.successor = successor;}public abstract void handleRequest(int request);//处理请求}2. 具体处理者(Concrete Handler)具体处理者是责任链中的具体实现类,它实现了抽象处理者所定义的方法和属性。
每个具体处理者只能处理自己“能力范围”内的请求。
当无法处理特定的请求时,具体处理者可以将该请求转移给下一个处理者。
如图所示:public class ConcreteHandlerA extends Handler {public void handleRequest(int request) {if (request < 10) {System.out.println(getClass().getName() + " 处理了 " + request);} else {successor.handleRequest(request);//转给下一个处理者}}}public class ConcreteHandlerB extends Handler {public void handleRequest(int request) {if (request < 20) {System.out.println(getClass().getName() + " 处理了 " + request);} else {successor.handleRequest(request);//转给下一个处理者}}}3. 客户端(Client)客户端是使用责任链模式的入口,在客户端中可以创建责任链并将请求送入责任链中处理,也可以给责任链添加新的处理者。
java责任链模式及项目实际运用1.前言上次我们认识了java责任链模式的设计,那么接下来将给大家展示责任链模式项目中的实际运用。
如何快速搭建责任链模式的项目中运用。
2.简单技术准备我们要在项目中使用借助这样的几个知识的组合运用,才能更好的诠释。
必备技能:简单注解的定义;Spring拦截器的使用;简答的责任链模式的定义;拥有以前的准备的知识点的,我们就可以快速搭建责任链来做安全校验了。
3. 场景模拟场景:系统中我们需要一些安全校验结构,如登陆校验与角色校验。
接下来我们使用责任链模式来开发这个流程化校验。
4. 设计模式我们将设计一个web项目,采用springmvc 框架。
开发语言使用JAVA。
执行过程执行过程:SpringMVC拦截器 --- > 拦截指定注解 --- > 进入责任链处理5编码实战5.1 注解定义定义一个Permission注解其中是枚举类型的校验类型5.2拦截器定义我们定义拦截器PermissionInterceptor,实际上也是注解解析器。
我们将借助于springMVC来做拦截器。
我们使用springMVC 拦截器可以实现org.springframework.web.servlet.HandlerInterceptor 重写接口的三个方法即可。
我们一起看看是如何实现的。
我们定义好了拦截器,下一步需要将我们拦截器配置给我们springMVC容器中管理在servlet-context.xml 上配置定义好的拦截器。
这样我们就将拦截器配置给springMVC容器了。
5.3 责任链的设计5.3.1 抽象责任链PermissionAbstractHandlerChain:定义责任链处理规则。
5.3.2 具体业务处理对象PermissionWithNone PermissionWithLogin PermissionWithRole 都需要继承抽象处理链。
5.3.2.1. PermissionWithNone 不做校验5.3.2.2. PermissionWithLogin 登陆校验备注 boolean status = VerificationLoginUtil.isLoginedStatus(request); 此处的登陆校验需要结合实际的业务来做。
Chain of Responsibility模式在实际Java开发中的使用方法Chain of Responsibility(责任链)模式是一种行为型设计模式,主要用于将请求发送给多个对象进行处理,直到找到能够处理请求的对象为止。
这种模式可以有效地降低代码的耦合性,避免将处理请求的代码嵌入到客户端中。
在实际的Java开发过程中,Chain of Responsibility模式可以应用于很多场景中。
本文将介绍Chain of Responsibility模式的基本概念以及在实际Java开发中的使用方法。
一、基本概念Chain of Responsibility模式是一种经典的处理请求的方式。
它由多个Handler对象(处理器对象)构成,每个Handler对象负责处理一种请求。
如果当前的Handler对象无法处理请求,它会将请求传递给下一个Handler对象,直到找到能够处理请求的Handler对象为止。
这样,在不同的场景中,我们只需要根据实际情况配置不同的Handler对象,就可以处理不同类型的请求。
Chain of Responsibility模式中的Handler对象一般包含两个基本操作:handle()和setSuccessor()。
handle()方法用于处理请求,setSuccessor()方法用于设置下一个处理器对象。
下面是Chain of Responsibility模式的基本结构:```public abstract class Handler {protected Handler successor;public void setSuccessor(Handler successor) {this.successor = successor;}public abstract void handle(Request request);}public class ConcreteHandler1 extends Handler {public void handle(Request request) {if (可以处理请求) {// 处理请求} else {successor.handle(request);}}}public class ConcreteHandler2 extends Handler { public void handle(Request request) {if (可以处理请求) {// 处理请求} else {successor.handle(request);}}}// ...```在实际应用中,我们可以根据具体的实现需求,定义不同的Handler类,实现不同的handle()方法逻辑,从而处理不同类型的请求。
设计模式之责任链模式(ChainofResponsibility)详解及代码⽰例⼀、责任链模式的定义与特点 责任链(Chain of Responsibility)模式的定义:责任链模式也叫职责链模式,为了避免请求发送者与多个请求处理者耦合在⼀起,将所有请求的处理者通过前⼀对象记住其下⼀个对象的引⽤⽽连成⼀条链;当有请求发⽣时,可将请求沿着这条链传递,直到有对象处理它为⽌。
在责任链模式中,客户只需要将请求发送到责任链上即可,⽆须关⼼请求的处理细节和请求的传递过程,所以责任链将请求的发送者和请求的处理者解耦了。
⼆、责任链模式优缺点 责任链模式是⼀种对象⾏为型模式,其主要优点如下:降低了对象之间的耦合度。
该模式使得⼀个对象⽆须知道到底是哪⼀个对象处理其请求以及链的结构,发送者和接收者也⽆须拥有对⽅的明确信息。
增强了系统的可扩展性。
可以根据需要增加新的请求处理类,满⾜开闭原则。
增强了给对象指派职责的灵活性。
当⼯作流程发⽣变化,可以动态地改变链内的成员或者调动它们的次序,也可动态地新增或者删除责任。
责任链简化了对象之间的连接。
每个对象只需保持⼀个指向其后继者的引⽤,不需保持其他所有处理者的引⽤,这避免了使⽤众多的 if 或者 if···else 语句。
责任分担。
每个类只需要处理⾃⼰该处理的⼯作,不该处理的传递给下⼀个对象完成,明确各类的责任范围,符合类的单⼀职责原则。
其主要缺点如下:不能保证每个请求⼀定被处理。
由于⼀个请求没有明确的接收者,所以不能保证它⼀定会被处理,该请求可能⼀直传到链的末端都得不到处理。
对⽐较长的职责链,请求的处理可能涉及多个处理对象,系统性能将受到⼀定影响。
职责链建⽴的合理性要靠客户端来保证,增加了客户端的复杂性,可能会由于职责链的错误设置⽽导致系统出错,如可能会造成循环调⽤。
三、责任链模式的实现 通常情况下,可以通过数据链表来实现职责链模式的数据结构。
责任链模式职责链模式(Chain of Responsibility):使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。
将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
适用场景:1、有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定;2、在不明确指定接收者的情况下,向多个对象中的一个提交一个请求;3、处理一个请求的对象集合应被动态指定。
通用类图:650) this.width=650;">在大学里面当班干部,时常要向上级申请各方面的东西。
譬如申请全班外出秋游,普通同学将申请表交给班长,班长签字之后交给辅导员,辅导员批准之后上交到主任办公室…就是这样,一个请求(这里是一份申请表)有时候需要经过好几个级别的处理者(这里是辅导员、主任)的审查才能够最终被确定可行与否。
在这里表现出来的是一个职责链,即不同的处理者对同一个请求可能担负着不同的处理方式、权限,但是我们希望这个请求必须到达最终拍板的处理者(否则秋游就没戏了)。
这种关系就很适合使用职责链模式了。
类图结构如下:650) this.width=650;">代码实现如下:// 全局变量,接口类型/** * 使用Java中的interface定义全局变量,可根据具体需要在* 具体的包中使用静态导入相关的全局变量,语法如下:* import static package01.package02.*; */ interface Levels { public static final int LEVEL_01 = 1;public static final int LEVEL_02 = 2; public static final int LEVEL_03 = 3; }// 抽象请求类abstract class AbstractRequest{ private String content = null; public AbstractRequest(String content) { this.content = content; } public String getContent(){ return this.content; } // 获得请求的级别public abstract int getRequestLevel(); }// 具体请求类01 class Request01 extends AbstractRequest { public Request01(String content) { super(content); } @Override public int getRequestLevel() { returnLevels.LEVEL_01; } } // 具体请求类02 class Request02 extends AbstractRequest { publicRequest02(String content){ super(content); } @Override public int getRequestLevel() { returnLevels.LEVEL_02; } } // 具体请求类03 class Request03 extends AbstractRequest { public Request03(String content){ super(content); } @Override public int getRequestLevel() { returnLevels.LEVEL_03; } }// 抽象处理者类,abstract class AbstractHandler{ // 责任链的下一个节点,即处理者private AbstractHandler nextHandler = null; // 捕获具体请求并进行处理,或是将请求传递到责任链的下一级别public final void handleRequest(AbstractRequest request) { // 若该请求与当前处理者的级别层次相对应,则由自己进行处理if (this.getHandlerLevel() == request.getRequestLevel()){ this.handle(request); } else{ // 当前处理者不能胜任,则传递至职责链的下一节点if (this.nextHandler != null) { System.out.println("当前处理者-0" + this.getHandlerLevel() + " 不足以处理请求-0" + request.getRequestLevel());// 这里使用了递归调用this.nextHandler.handleRequest(request); } else { System.out.println("职责链上的所有处理者都不能胜任该请求..."); } } } // 设置责任链中的下一个处理者public void setNextHandler(AbstractHandler nextHandler){ this.nextHandler = nextHandler; }// 获取当前处理者的级别protected abstract int getHandlerLevel(); // 定义链中每个处理者具体的处理方式protected abstract voidhandle(AbstractRequest request); }// 具体处理者-01 class Handler01 extends AbstractHandler { @Override protected int getHandlerLevel() { returnLevels.LEVEL_01; } @Override protected void handle(AbstractRequest request){ System.out.println("处理者-01 处理" + request.getContent() + "\n"); } } // 具体处理者-02 class Handler02 extends AbstractHandler{ @Override protected int getHandlerLevel(){ return Levels.LEVEL_02; }@Override protected void handle(AbstractRequest request) { System.out.println("处理者-02 处理" + request.getContent()+ "\n"); } } // 具体处理者-03 class Handler03 extends AbstractHandler{ @Override protected int getHandlerLevel() { return Levels.LEVEL_03; }@Override protected void handle(AbstractRequest request) { System.out.println("处理者-03 处理" + request.getContent()+ "\n"); } }// 测试类public class Client { public static void main(String[] args) { // 创建指责链的所有节点AbstractHandler handler01 = new Handler01(); AbstractHandler handler02 = new Handler02(); AbstractHandler handler03 = new Handler03();// 进行链的组装,即头尾相连,一层套一层handler01.setNextHandler(handler02);handler02.setNextHandler(handler03); // 创建请求并提交到指责链中进行处理AbstractRequest request01 = new Request01("请求-01"); AbstractRequest request02 = new Request02("请求-02"); AbstractRequest request03 = new Request03("请求-03");// 每次提交都是从链头开始遍历handler01.handleRequest(request01);handler01.handleRequest(request02);handler01.handleRequest(request03); } }测试结果:处理者-01 处理请求-01 当前处理者-01 不足以处理请求-02 处理者-02 处理请求-02 当前处理者-01 不足以处理请求-03 当前处理者-02 不足以处理请求-03 处理者-03 处理请求-03在上面抽象处理者AbstractHandler 类的handleRequest() 方法中,被protected 修饰,并且该方法中调用了两个必须被子类覆盖实现的抽象方法,这里是使用了模板方法模式(Template Mehtod)。
设计模式-责任链模式在实际项⽬中的使⽤ 最近⼀次迭代,参与了公司数据应⽤平台的开发,其中负责的⼀块功能早早的就完成了代码的编写⼯作,即将进⼊测试阶段,因为有时间思考和总结代码编写中遇到的难题,便想着将代码做⼀次重构:其中优化的⼀个功能就是关于数据平台敏感字段的收集功能描述:数据平台敏感字段的收集:提供 service ⽅法,查询是否需要扫描表做触发式收集,指定具体实例与库的表,随机取 N ⾏(1~max(id) 之间);a.对每⼀⾏的每⼀个字段的值(取⾮ null ⾮空的值)做正则匹配b. 对每⼀⾏的每⼀个字段的值看是否包含了敏感字段的 keyc. 对每⼀⾏的每⼀个字段名做匹配;如果匹配,再判断该字段为敏感字段还是疑似敏感字段,添加到 secret_column 中开始的版本:/*** 敏感字段的收集** @param instance* @param schema*/public void collectSecretColumn(String instance, String schema, String table) {//查询该表是否扫描过CollectedTable collectedTable = collectedTableService.getCollectedTable(instance, schema, table);if (collectedTable != null) {return;}//随机获取n⾏记录JdbcResult query = getPartQueryResult(instance, schema, table);if (query == null || (query != null && StringUtils.isNotBlank(query.getQueryErrorMsg()))) {throw new CjjServerException(500, "系统繁忙,请稍后再试");}//key为column value为值的集合Map<String, List<String>> groupMap = convertListToMap(query.getResult());Set<Map.Entry<String, List<String>>> entries = groupMap.entrySet();List<SecretContainedKey> secretContainedKeys = secretContainedKeyMapper.listSecretContainedKeys();List<SecretValueRegex> secretValueRegexs = secretValueRegexService.getSecretValueRegexes();for (Map.Entry<String, List<String>> entry : entries) {//获取columnString column = entry.getKey();List<String> values = entry.getValue();//判断该字段是否已经存在在敏感字段表中boolean secretColumnExist = isSecretColumnExist(instance, schema, table, column);if (secretColumnExist) {continue;}//c:对字段名做匹配boolean isValueContaninsKey = secretContainedKeyService.columnKeyIsContainsKey(instance, schema, table, secretContainedKeys, column);if (isValueContaninsKey) {continue;}//b:字段的值是否包含敏感字段的keyboolean isContainsKey = secretContainedKeyService.columnValueIsContainsKey(instance, schema, table, secretContainedKeys, column, values);if (isContainsKey) {continue;}//a:通过正则匹配字段值secretValueRegexService.regexMatch(instance, schema, table, column, values, secretValueRegexs);}CollectedTable collected = CollectedTable.builder().instanceName(instance).schemaName(schema).tableName(table).build();collectedTableMapper.save(collected);}可以看出逻辑都散落在for循环中通过责任链模式:后代码:/*** 敏感字段的收集** @param instance* @param schemaCollectedTable collectedTable = collectedTableService.getCollectedTable(instance, schema, table);if (collectedTable != null) {return;}//随机获取n⾏记录JdbcResult query = getPartQueryResult(instance, schema, table);if (query == null || (query != null && StringUtils.isNotBlank(query.getQueryErrorMsg()))) {throw new CjjServerException(500, "系统繁忙,请稍后再试");}//key为column value为值的集合Map<String, List<String>> groupMap = convertListToMap(query.getResult());Set<Map.Entry<String, List<String>>> entries = groupMap.entrySet();secretValueRegexHandler.setSuccessor(secretValueContainedKeyHandler);secretValueContainedKeyHandler.setSuccessor(secretColumnContainedKeyHandler);for (Map.Entry<String, List<String>> entry : entries) {//获取columnString column = entry.getKey();List<String> values = entry.getValue();//判断该字段是否已经存在在敏感字段表中boolean secretColumnExist = isSecretColumnExist(instance, schema, table, column);if (secretColumnExist) {continue;}secretValueRegexHandler.handleCollect(instance, schema, table, column, values);}CollectedTable collected = CollectedTable.builder().instanceName(instance).schemaName(schema).tableName(table).build();collectedTableMapper.save(collected);} 可以看出这边的代码量减少了,看起来结构更清晰了为了⽅便理解:我会列出部分代码供⼤家参考package cn.caijiajia.firekylin.service.secret;import java.util.List;/*** 责任链设计模式** @author chenlang* date 2018/7/13*/public abstract class CollectSecretColumnHandler {protected CollectSecretColumnHandler successor;public abstract void handleCollect(String instance, String schema, String table, String column, List<String> values); /*** 获取责任对象*/public CollectSecretColumnHandler getSuccessor() {return successor;}/*** 设置后继的责任对象*/public void setSuccessor(CollectSecretColumnHandler successor) {this.successor = successor;}}package cn.caijiajia.firekylin.service.secret;import cn.caijiajia.firekylin.domain.SecretContainedKey;import cn.caijiajia.firekylin.mapper.SecretContainedKeyMapper;import cn.caijiajia.firekylin.service.SecretColumnService;import org.springframework.beans.factory.annotation.Autowired;import ponent;import java.util.List;import java.util.Map;import java.util.Set;import java.util.stream.Collectors;public class SecretColumnContainedKeyHandler extends CollectSecretColumnHandler {@Autowiredprivate SecretColumnService secretColumnService;@Autowiredprivate SecretContainedKeyMapper secretContainedKeyMapper;@Overridepublic void handleCollect(String instance, String schema, String table, String column, List<String> values) {List<SecretContainedKey> secretContainedKeys = secretContainedKeyMapper.listSecretContainedKeys();boolean columnKeyIsContainsKey = columnKeyIsContainsKey(instance, schema, table, secretContainedKeys, column);if (!columnKeyIsContainsKey) {}}public boolean columnKeyIsContainsKey(String instance, String schema, String table, List<SecretContainedKey> secretContainedKeys, String column) {SecretContainedKey secretContainedKeyByColumn = getSecretContainedKeyByColumn(column, secretContainedKeys);if (secretContainedKeyByColumn != null) {secretColumnService.saveSecretColumn(instance, schema, table, column, secretContainedKeyByColumn.getSecretType(), secretContainedKeyByColumn.getColumnType()); return true;}return false;}/*** 字段名是否包含敏感的key** @param column* @param secretContainedKeys* @return*/public SecretContainedKey getSecretContainedKeyByColumn(String column, List<SecretContainedKey> secretContainedKeys) {Map<String, SecretContainedKey> keysMap = secretContainedKeys.stream().collect(Collectors.toMap(SecretContainedKey::getContainedKey, a -> a));Set<Map.Entry<String, SecretContainedKey>> entries = keysMap.entrySet();for (Map.Entry<String, SecretContainedKey> entry : entries) {String key = entry.getKey();boolean contains = column.toLowerCase().contains(key);if (contains) {return keysMap.get(key);}}return null;}}package cn.caijiajia.firekylin.service.secret;import cn.caijiajia.firekylin.domain.SecretContainedKey;import cn.caijiajia.firekylin.mapper.SecretContainedKeyMapper;import cn.caijiajia.firekylin.service.SecretColumnService;import org.springframework.beans.factory.annotation.Autowired;import ponent;import java.util.List;/*** @author chenlang* date 2018/7/13*/@Componentpublic class SecretValueContainedKeyHandler extends CollectSecretColumnHandler {@Autowiredprivate SecretColumnService secretColumnService;@Autowiredprivate SecretContainedKeyMapper secretContainedKeyMapper;@Overridepublic void handleCollect(String instance, String schema, String table, String column, List<String> values) {List<SecretContainedKey> secretContainedKeys = secretContainedKeyMapper.listSecretContainedKeys();boolean columnValueIsContainsKey = columnValueIsContainsKey(instance, schema, table, secretContainedKeys, column, values);if (!columnValueIsContainsKey) {getSuccessor().handleCollect(instance, schema, table, column, values);}}public boolean columnValueIsContainsKey(String instance, String schema, String table, List<SecretContainedKey> secretContainedKeys, String column, List<String> values) {for (SecretContainedKey secretContainedKey : secretContainedKeys) {boolean isSecretColumnContainsKey = isSecretColumnContainsKey(values, secretContainedKey);if (isSecretColumnContainsKey) {secretColumnService.saveSecretColumn(instance, schema, table, column, secretContainedKey.getSecretType(), secretContainedKey.getColumnType());/*** 字段值是否包含敏感字段的key** @param columnValues* @param secretContainedKey* @return*/public boolean isSecretColumnContainsKey(List<String> columnValues, SecretContainedKey secretContainedKey) {for (String columnValue : columnValues) {if (columnValue.toLowerCase().contains(secretContainedKey.getContainedKey())) {return true;}}return false;}}package cn.caijiajia.firekylin.service.secret;import cn.caijiajia.firekylin.constant.SecretType;import cn.caijiajia.firekylin.domain.SecretValueRegex;import cn.caijiajia.firekylin.service.SecretColumnService;import cn.caijiajia.firekylin.service.SecretValueRegexService;import org.springframework.beans.factory.annotation.Autowired;import ponent;import org.springframework.util.CollectionUtils;import java.util.List;import java.util.regex.Pattern;/*** 正则匹配收集敏感字段** @author chenlang* date 2018/7/13*/@Componentpublic class SecretValueRegexHandler extends CollectSecretColumnHandler {@Autowiredprivate SecretColumnService secretColumnService;@Autowiredprivate SecretValueRegexService secretValueRegexService;@Overridepublic void handleCollect(String instance, String schema, String table, String column, List<String> values) {List<SecretValueRegex> secretValueRegexs = secretValueRegexService.getSecretValueRegexes();boolean regexMatch = regexMatch(instance, schema, table, column, values, secretValueRegexs);if (!regexMatch) {if (getSuccessor() != null) {getSuccessor().handleCollect(instance, schema, table, column, values);}}}public boolean regexMatch(String instance, String schema, String table, String column, List<String> values, List<SecretValueRegex> secretValueRegexs) { for (SecretValueRegex secretValueRegex : secretValueRegexs) {boolean secretByRegex = isSecretByRegex(values, secretValueRegex.getPattern());if (secretByRegex) {secretColumnService.saveSecretColumn(instance, schema, table, column, SecretType.SECRECT, secretValueRegex.getCode());return true;}}return false;}/*** 字段值是否匹配正则表达式** @param columnValues* @return*/public boolean isSecretByRegex(List<String> columnValues, Pattern compile) {if (CollectionUtils.isEmpty(columnValues)) {return false;}for (String columnValue : columnValues) {boolean isSecret = compile.matcher(columnValue).matches();if (!isSecret) {}现在每种情况对应⼀种handler,同时继承⾃CollectSecretColumnHandler。
责任链模式的应用场景
责任链模式是一种行为设计模式,它通过一系列的处理器对象形成一个链,每个处理器都有机会处理请求,直到请求被处理或者到达链的末端。
该模式常用于解耦发送者和接收者,将请求沿着链传递,并动态地决定由哪个处理器来处理请求。
责任链模式的应用场景非常广泛,下面将介绍几个典型的应用场景:
1. 请求处理链:在一个系统中,可能存在多个处理器,每个处理器负责不同的处理逻辑。
通过使用责任链模式,可以将这些处理器连接成一个处理链,每个请求按照处理链的顺序依次经过处理器进行处理,直到找到合适的处理器处理请求或者请求被拒绝。
这种模式可以实现请求的动态处理和灵活的扩展,提高系统的可维护性和可扩展性。
2. 日志记录:在日志记录的场景中,可以使用责任链模式来实现不同级别的日志记录。
例如,系统中分为普通日志、警告日志和错误日志三个级别,每个级别对应一个处理器,处理器根据日志级别来决定是否处理该日志,以及如何处理。
这样,请求日志的对象只需要将日志传递给处理链的第一个处理器,而无需关心具体的处理过程,大大简化了代码的编写和维护。
3. 身份认证:在网络应用中,身份认证是一个重要的功能。
责任链模式可以用于实现不同方式的身份认证,例如用户名密码认证、邮
箱验证码认证、短信验证码认证等。
每个认证方式都可以由一个处理器来处理,根据请求的方式和内容来判断是否通过认证。
如果一个处理器无法认证通过,则将请求传递给下一个处理器进行处理,直到找到合适的处理器或者认证失败。
4. 资源分配:在资源分配的场景中,可以使用责任链模式来实现资源的动态分配和优化。
例如,一个服务器集群中存在多台服务器,每台服务器负责处理不同类型的请求。
通过使用责任链模式,可以将请求按照类型分发给不同的服务器进行处理,实现负载均衡和资源优化。
5. 异常处理:在系统开发中,异常处理是一个重要的环节。
责任链模式可以用于实现异常的捕获和处理。
可以将异常捕获的逻辑封装在处理器中,当一个异常被抛出时,责任链上的处理器会依次尝试处理该异常,直到找到合适的处理器或者异常无法处理。
总的来说,责任链模式适用于需要将请求和处理解耦的场景,同时又需要动态地组织处理逻辑的场景。
通过使用责任链模式,可以实现请求的动态处理、灵活的扩展和简化的代码编写,提高系统的可维护性和可扩展性。
同时,该模式还可以用于日志记录、身份认证、资源分配和异常处理等多个领域。