第十六章行为性模式—职责链模式

news/2024/11/13 4:17:00/

文章目录

  • 职责链模式
    • 解决的问题
    • 结构
    • 实例
    • 存在的问题
  • JavaWeb 源码 - FilterChain

行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象无法单独完成的任务,它涉及算法与对象间职责的分配。行为型模式分为类行为模式和对象行为模式:

  • 类行为模式:采用继承机制来在类间分派行为

  • 对象行为模式:采用组合或聚合在对象间分配行为

由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性。

行为型模式分为:

  • 模板方法模式
  • 策略模式
  • 命令模式
  • 职责链模式
  • 状态模式
  • 观察者模式
  • 中介者模式
  • 迭代器模式
  • 访问者模式
  • 备忘录模式
  • 解释器模式

以上 11 种行为型模式,除了模板方法模式解释器模式是类行为型模式,其他的全部属于对象行为型模式。

职责链模式

职责链模式:又名责任链模式,为了避免请求发送者与多个请求处理者耦合在一起,将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。

解决的问题

在现实生活中,常常会出现这样的事例:一个请求有多个对象可以处理,但每个对象的处理条件或权限不同。例如,公司员工请假,可批假的领导有【部门负责人】、【副总经理】、【总经理】等,但每个领导能批准的天数不同,员工必须根据自己要请假的天数去找不同的领导签名,也就是说员工必须记住每个领导的姓名、电话和地址等信息,这增加了难度。

结构

  • 抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。

  • 具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。

  • 客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。

实例

在这里插入图片描述

请假条类

@Getter
public class LeaveRequest {//姓名private String name;//请假天数private int num;//请假内容private String content;public LeaveRequest(String name, int num, String content) {this.name = name;this.num = num;this.content = content;}
}

抽象处理者

public abstract class Handler {protected final static int NUM_ONE=1;protected final static int NUM_THREE = 3;protected final static int NUM_SEVEN = 7;//该领导处理的请求天数区间private int numStart;private int numEnd;//声明后继者(声明上级领导)private Handler nextHandler;public Handler(int numStart) {this.numStart = numStart;}public Handler(int numStart, int numEnd) {this.numStart = numStart;this.numEnd = numEnd;}// 设置上级领导对象public Handler(Handler nextHandler) {this.nextHandler = nextHandler;}//各级领导处理请求条的方法protected  abstract  void handleLeave(LeaveRequest leaveRequest);//提交请求条public final void  submit(LeaveRequest leaveRequest){if(leaveRequest.getNum()>NUM_SEVEN){System.out.println("请假天数过多");return;}//该领导进行审批this.handleLeave(leaveRequest);if(this.nextHandler != null && leaveRequest.getNum() > this.numEnd){//提交给上级领导进行审批this.nextHandler.submit(leaveRequest);}else {System.out.println("流程结束!");}}
}

具体处理者

public class GroupLeader extends Handler{public GroupLeader() {super(0,Handler.NUM_ONE);}@Overrideprotected void handleLeave(LeaveRequest leaveRequest) {System.out.println(leaveRequest.getName() + "请假" + leaveRequest.getNum() + "天," + leaveRequest.getContent() + "。");System.out.println("小组长审批:同意");}
}
public class Manager extends Handler{public Manager() {super(Handler.NUM_ONE, Handler.NUM_THREE);}@Overrideprotected void handleLeave(LeaveRequest leaveRequest) {System.out.println(leaveRequest.getName() + "请假" + leaveRequest.getNum() + "天," + leaveRequest.getContent() + "。");System.out.println("部门经理审批:同意");}
}
public class GeneralManager extends Handler{public GeneralManager() {super(Handler.NUM_THREE, Handler.NUM_SEVEN);}@Overrideprotected void handleLeave(LeaveRequest leaveRequest) {System.out.println(leaveRequest.getName() + "请假" + leaveRequest.getNum() + "天," + leaveRequest.getContent() + "。");System.out.println("总经理审批:同意");}
}

客户类

public class Client {public static void main(String[] args) {//创建一个请假条对象LeaveRequest leaveRequest = new LeaveRequest("小明", 7, "身体不适");//创建各级领导对象GroupLeader groupLeader = new GroupLeader();//小组长Manager manager = new Manager();//部门经理GeneralManager generalManager = new GeneralManager();//总经理//设置处理者链groupLeader.setNextHandler(manager);manager.setNextHandler(generalManager);//小明提交请假申请groupLeader.submit(leaveRequest);}
}

存在的问题

优点:

  • 降低了对象之间的耦合度,该模式降低了请求发送者和接收者的耦合度。

  • 增强了系统的可扩展性,可以根据需要增加新的请求处理类,满足开闭原则。

  • 增强了给对象指派职责的灵活性,当工作流程发生变化,可以动态地改变链内的成员或者修改它们的次序,也可动态地新增或者删除责任。

  • 责任链简化了对象之间的连接,一个对象只需保持一个指向其后继者的引用,不需保持其他所有处理者的引用,这避免了使用众多的 if 或者 if···else 语句。

  • 责任分担,每个类只需要处理自己该处理的工作,不能处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则。

缺点:

  • 不能保证每个请求一定被处理。由于一个请求没有明确的接收者,所以不能保证它一定会被处理,该请求可能一直传到链的末端都得不到处理。
  • 对比较长的职责链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响。
  • 职责链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能会由于职责链的错误设置而导致系统出错,如可能会造成循环调用。

JavaWeb 源码 - FilterChain

在 JavaWeb 应用开发中,FilterChain 是职责链模式的典型应用,以下是 Filter 的模拟实现分析:

模拟 Web 请求 Request 以及 Web 响应 Response:

public interface Request{
}public interface Response{
}

模拟 Web 过滤器 Filter:

public interface Filter {void doFilter(Request req,Response res,FilterChain c);
}

模拟实现具体过滤器:

public class FirstFilter implements Filter {@Overridepublic void doFilter(Request request, Response response, FilterChain chain) {System.out.println("过滤器1 前置处理");// 先执行所有request再倒序执行所有responsechain.doFilter(request, response);System.out.println("过滤器1 后置处理");}
}public class SecondFilter  implements Filter {@Overridepublic void doFilter(Request request, Response response, FilterChain chain) {System.out.println("过滤器2 前置处理");// 先执行所有request再倒序执行所有responsechain.doFilter(request, response);System.out.println("过滤器2 后置处理");}
}

模拟实现过滤器链 FilterChain:

public class FilterChain {private List<Filter> filters = new ArrayList<>();private int index = 0;// 链式调用public FilterChain addFilter(Filter filter) {this.filters.add(filter);return this;}// 过滤操作public void doFilter(Request request, Response response) {if (index == filters.size()) {return;}Filter filter = filters.get(index);index++;filter.doFilter(request, response, this);}
}

测试类:

public class Client {public static void main(String[] args) {Request  req = null;Response res = null ;FilterChain filterChain = new FilterChain();filterChain.addFilter(new FirstFilter()).addFilter(new SecondFilter());filterChain.doFilter(req,res);
}}
过滤器1 前置处理
过滤器2 前置处理
过滤器2 后置处理
过滤器1 后置处理

http://www.ppmy.cn/news/119290.html

相关文章

函数栈帧的创建与销毁

目录 1、寄存器的分类与作用 2、测试代码与所需要的知识点 2.1、测试代码 2.2 、关于main函数的调用 2.3、关于栈、压栈、出栈简介 3、main函数栈帧的创建与分析 3 .1、push edp 3.2、mov ebp&#xff0c;esp 3.3、sub esp&#xff0c;0E4h 3.4、push ebx&#xf…

40V 高精度 LDO 稳压器-QX6126

QX6126 是一款支持最高 40V 输入的 三端 LDO 稳压器芯片。其内置高精度的 输出运算放大器&#xff0c;进而可得到精准且稳定 的输出电压。 芯片具有低静态电流&#xff0c;并可实现最大 100mA 的电流输出&#xff0c;并具有短路保护、温 度保护等功能。 QX6126 采用 SOT23、S…

STM32自学笔记-5-SPI和Flash芯片2

在W25Qxx.c中&#xff0c;可以重点看以下几个函数 BSP_W25Qx_WriteEnable()函数 uint8_t BSP_W25Qx_WriteEnable(void) {uint8_t cmd[] {0x06};uint32_t tickstart HAL_GetTick(); //开始计时W25Qx_Enable(); //将NSS拉低&#xff0c;使芯片可操作HAL_SPI_Transmit(&h…

LED台灯方案:QX6126+QX5567

QX6126是一款支持40V输入的三端LDO稳压器芯片。其内置高精度的输出运算放大器&#xff0c;进而可得到精准且稳定的输出电压。 芯片具有低静态电流&#xff0c;并可实现最大100mA的电流输出&#xff0c;并具有短路保护、温度保护等功能。 QX6126采用SOT-23-3、SOT-89封装&…

小风扇专用芯片-QX5311F

概述 QX5311F是一款集成了锂电池线性充电箮和三种档位输出驱动的手持风扇驱动芯片&#xff0c;只需极少的外接元件&#xff0c;便能适用于手持风扇等便携式产品的应用。 QX5311F 根据电池电压的不同可分别有涓流充电&#xff0c;恒流充电和恒压充电等三种充电模式。浮流电压被固…

创建一个长度是100的字符串数组,使用长度是2的随机字符填充该字符串数组,统计这个字符串数组里重复的字符串有多少种(忽略大小写)

创建一个长度是100的字符串数组 使用长度是2的随机字符填充该字符串数组 统计这个字符串数组里重复的字符串有多少种(忽略大小写) 例如 输出: 20个字符串一行 共5行 01 0S 1M 1q 20 2R 2S 3d 3k 3x 43 4A 4R 5T 7C 7U 7e 7k 80 88 8p AD AG AY BF BO Db E2 Eg El GF Gm HC HO I…

数据库实验 | 第5关:使用游标的存储过程

任务描述 本关任务&#xff1a; jdxx数据表有四个字段&#xff0c;分别是省份(sf)、城市(cs)、区县(qxmc)、街道(name)。 例如&#xff0c;查询天心区(qxmc)的所有字段的值结果如图所示 任务要求 建立存储过程 tjdq(in sf varchar(10)) 输入省份的名称&#xff0c;将该省份…

是男人就下100层(简仿)

近 来&#xff0c;事情不多&#xff0c;闲暇之时&#xff0c;就想写个简单的游戏练练手。太复杂了&#xff0c;不使用游戏引擎来做&#xff0c;是非常困难的。这里&#xff0c;其实也没有打算说&#xff0c;开发一款游戏上线&#xff0c;就是练习如何自定义一个View。我想啊想&…