击鼓传花java_击鼓传花联想到了Java设计模式:责任链模式
应用场景
http web请求处理,请求过来后将经过转码、解析、参数封装、鉴权等一系列的处理(责任),而且要经过多少处理是可以灵活调整的
那么该怎么做呢?
将所有的处理都写在一个类中行不行呢?
分成多个类又该如何灵活的组合在一起呢?
简单示例
Request类:
public interface Request{
//do something...
}
复制代码
ResponsibilityChain类:
public class ResponsibilityChain{
private List responsibilityList = new ArrayList<>();
private Integer index = 0;
public void process(Request request){
if (this.index < responsibilityList.size()) {
this.responsibilityList.get(index++).process(request, this);
}
}
/** 加入链中 */
public void register(Responsibility responsibility){
this.responsibilityList.add(responsibility);
}
}
复制代码
Responsibility接口:
public interface Responsibility{
void process(Request request, ResponsibilityChain chain);
}
复制代码
Responsibility实现类:
public class ResponsibilityA implements Responsibility{
@Override
public void process(Request request, ResponsibilityChain chain){
System.out.println("转码");
chain.process(request);
}
}
复制代码
public class ResponsibilityB implements Responsibility{
@Override
public void process(Request request, ResponsibilityChain chain){
System.out.println("解析");
chain.process(request);
}
}
复制代码
public class ResponsibilityC implements Responsibility{
@Override
public void process(Request request, ResponsibilityChain chain){
System.out.println("参数封装");
chain.process(request);
}
}
复制代码
public class ResponsibilityD implements Responsibility{
@Override
public void process(Request request, ResponsibilityChain chain){
System.out.println("鉴权");
chain.process(request);
}
}
复制代码
测试类:
public class Test{
public static void main(String[] args){
ResponsibilityChain chain = new ResponsibilityChain();
chain.register(new ResponsibilityA());
chain.register(new ResponsibilityB());
chain.register(new ResponsibilityC());
chain.register(new ResponsibilityD());
chain.process(new Request() {
});
}
}
复制代码
类图:
责任链模式
定义
所有的处理者,都加入到这个链式,一个处理完后,转给下一个
或者说每个接收者都包含对另一个接收者的引用,如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者
抽象出责任接口,具体责任逻辑实现接口
根据处理过程需要,将具体实现组合成链
使用者使用链
典型的代表:Filter、Interceptor
意图
避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止
主要解决问题
职责链上的处理者负责处理请求,客户端只需要将请求发送到职责链上就行了,不需要关系处理的细节和请求的传递,请求的发送者和处理者解耦了
何时使用
系统已经有一个由处理者对象组成的链,这个链可能有合成模式给出
有多于一个的处理者对象会处理一个请求,而且事先并不清楚到底由哪一个处理者对象处理一个请求,处理者对象是动态确定的
系统想发出一个请求给多个处理者对象中的某一个,但是不明显指定哪一个处理者对象会处理该请求
处理一个请求的处理者对象集合需要动态的指定时
优缺点
优点:
发送者和接收者解耦,低耦合
简化了对象。使得对象不需要知道链的结构
通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任
增加新的请求处理类很方便
缺点:
不能保证请求一定被接收
系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用
可能不容易观察运行时的特征,有碍于除错
类图如下:
涉及到的角色:
抽象处理者(Handler)角色:定义一个处理请求的接口,如果需要,接口可以定义出一个方法,以设定和返回对下家的引用,这个角色通常由一个抽象类或者接口实现
具体处理者(ConcreteHandler)角色:具体处理者接收到请求后,可以选择将请求处理掉,或者传给下一个;具体处理者持有对下一个的引用,因此如果需要,具体处理者可以访问下一个
代码示例:
Handler类:
public abstract class Handler{
protected Handler successor;
/** 调用此方法处理请求 */
public abstract void handlerRequest();
/** 取值方法 */
public Handler getSuccessor(){
return successor;
}
/** 调用此方法设置下一个 */
public void setSuccessor(Handler successor){
this.successor = successor;
}
}
复制代码
ConcreteHandler类:
public class ConcreteHandler1 extends Handler{
@Override
public void handlerRequest(){
if (getSuccessor() != null) {
System.out.println("请求传递到下一个:" + getSuccessor().getClass().getName());
getSuccessor().handlerRequest();
} else {
System.out.println("请求在ConcreteHandler1被处理了");
}
}
}
复制代码
public class ConcreteHandler2 extends Handler{
@Override
public void handlerRequest(){
if (getSuccessor() != null) {
System.out.println("请求传递到下一个:" + getSuccessor());
getSuccessor().handlerRequest();
} else {
System.out.println("请求在ConcreteHandler2被处理了");
}
}
}
复制代码
客户端:
public class Client{
static private Handler handler1;
static private Handler handler2;
public static void main(String[] args){
handler1 = new ConcreteHandler1();
handler2 = new ConcreteHandler2();
handler1.setSuccessor(handler2);
handler1.handlerRequest();
}
}
复制代码
类图:
击鼓传花的故事
击鼓传花是一种热闹而又紧张的饮酒游戏,在酒宴上宾客依次坐定,由一人击鼓,开始击鼓时,花束就开始依次传递,鼓声一落,如果花束在谁手里,谁就开始饮酒了;下面以《红楼梦》中击鼓传花的故事,写一个小例子:
抽象接口Player类:
public abstract class Player{
private Player player;
/** 需要执行酒令的请求 */
abstract public void handlerRequest(int index);
/** 设置下一个传花人 */
public void setPlayer(Player player){
this.player = player;
}
/** 将花传给下一家,如果没有就结束 */
public void next(int index){
if (player != null) {
player.handlerRequest(index);
} else {
System.out.println("传花结束");
}
}
}
复制代码
参与击鼓传花的人:
public class JiaMu extends Player{
public JiaMu(Player player){
this.setPlayer(player);
}
@Override
public void handlerRequest(int index){
if (index == 1) {
System.out.println("贾母执行酒令");
} else {
System.out.println("贾母将花传给下一个");
next(index);
}
}
}
复制代码
public class JiaShe extends Player{
public JiaShe(Player player){
this.setPlayer(player);
}
@Override
public void handlerRequest(int index){
if (index == 2) {
System.out.println("贾赦执行酒令");
} else {
System.out.println("贾赦将花传给下一个");
next(index);
}
}
}
复制代码
public class JiaZheng extends Player{
public JiaZheng(Player player){
this.setPlayer(player);
}
@Override
public void handlerRequest(int index){
if (index == 3) {
System.out.println("贾政执行酒令");
} else {
System.out.println("贾政将花传给下一个");
next(index);
}
}
}
复制代码
public class JiaBaoYu extends Player{
public JiaBaoYu(Player player){
this.setPlayer(player);
}
@Override
public void handlerRequest(int index){
if (index == 4) {
System.out.println("贾宝玉执行酒令");
} else {
System.out.println("贾宝玉将花传给下一个");
next(index);
}
}
}
复制代码
public class JiaHuan extends Player{
public JiaHuan(Player player){
this.setPlayer(player);
}
@Override
public void handlerRequest(int index){
if (index == 5) {
System.out.println("贾环执行酒令");
} else {
System.out.println("贾环将花传给下一个");
next(index);
}
}
}
复制代码
击鼓者:
public class DrinkingGame{
static private Player player;
public static void main(String[] args){
player = new JiaMu(
new JiaShe(
new JiaZheng(
new JiaBaoYu(
new JiaHuan(null)))));
//设置第四个执行酒令
player.handlerRequest(4);
}
}
复制代码
类图:
击鼓传花java_击鼓传花联想到了Java设计模式:责任链模式相关推荐
- 玉帝传美猴王上天,大闹天宫之Java设计模式:命令模式
命令模式 示例 改进代码 命令模式 定义 意图 主要解决问题 何时使用 优缺点 玉帝传美猴王上天 命令模式和策略模式的区别 示例 系统需要设计一个命令行界面,用户可输入命令来执行某项功能,系统的功能会 ...
- 迭代器 java_百战程序员:Java设计模式之迭代器模式
迭代器是针对集合对象而生的,对于集合对象而言,必然涉及到集合元素的添加删除操作,同时也肯定支持遍历集合元素的操作,我们此时可以把遍历操作也放在集合对象中,但这样的话,集合对象就承担太多的责任了,面向对 ...
- 花了30天才肝出来,史上最全面Java设计模式总结,看完再也不会忘
本文所有内容均节选自<设计模式就该这样学> 序言 Design Patterns: Elements of Reusable Object-Oriented Software(以下简称&l ...
- 【2021最新】大佬花了半个月整理出来的Java后端学习路线,果断收藏了!
要成为一个符合 BAT.TMD 大厂要求的后端技术工程师,到底需要学哪些技术?后端技术学习路线是怎样的? 学习路线 话不多说,直接上刚画完的后端技术学习路线思维导图框架: 图中的每一个节点都可以点 ...
- 联易融Java社招一面
一:联易融Java社招一面 1:项目 主要问你负责什么模块,做什么业务,然后问下公司的项目架构.这个比较简单,只要把平时做过的说出来都还好. 2:Java基础 String类为什么不可以被继承? 多线 ...
- 有N个小朋友围成一圈玩击鼓传花游戏,将小朋友编号为1~N,从1号开始传花,每次传3个,拿到花的小朋友表演节目后退出,扔给后一位没有表演的同学,求同学们的表演次序?
有N个小朋友围成一圈玩击鼓传花游戏,将小朋友编号为1~N,从1号开始传花,每次传3个,拿到花的小朋友表演节目后退出,扔给后一位没有表演的同学,求同学们的表演次序? 例如:5个小朋友,从1号开始传花,第 ...
- 由QQ文件中转站超快速上传联想到
今天向QQ文件中转站上传了两个文件,一个30M,一个60M,都发现上传时间仅为1s, 猜想了一下,这里应该是有算法的,如果服务器上以及同样的文件了,就不需要用户再上传,而是直接给出文件链接,这样既减轻 ...
- 【SpringBoot学习】5、SpringBoot 实现文件上传,图片上传并显示功能
SpringBoot 实现文件上传,图片上传并显示功能 我先看一下<颈椎病康复指南>再给大家说怎么实现的这两个功能,毕竟只是一个新手,解决这种复杂点的问题(相对而言),还是需要花费大量时间 ...
- vue动态路由传参---query传参和params传参
当一个页面跳转到另一个页面时,组件结构相同,只是内容不同且地址栏后缀不同 ,这个地址栏的后缀就是参数,根据不同参数渲染不同的内容,这个跳转就叫路由传参. 当项目中组件间通过路由跳转,有时,我们需要传递 ...
最新文章
- 使用PyTorch从零开始实现YOLO-V3目标检测算法 (四)
- UVA 11401 - Triangle Counting
- python调用父类构造函数需要放在第一句吗_Python继承和调用父类构造函数
- java 关于日期的操作
- SVN工作笔记005---TortoiseSVN SendRpt.exe not found解决方案
- [转] Bound Service的三种方式(Binder、 Messenger、 AIDL)
- 非纯 []!()输出 始皇帝 推导过程
- Eclipse中集成SVN
- 【VS开发】VS2010 MFC中控件、对话框等背景颜色动态修改的方法
- 【Matlab学习笔记】【图像滤波去噪】中值滤波
- javascript 计时器,消失计时器
- 各省份的车牌简称 备案地区的简称
- 0基础可以考CPDA数据分析师证书吗
- 三菱触摸屏通讯错误_s7-200和三菱触摸屏通讯的问题
- 小米4 android6.01的开发者模式开启方法
- 你真正付出了全部努力了吗?
- Ubuntu cd 命令
- mysql校对集_MySQL校对集问题的教程
- 【约束优先级问题二】动态高度cell
- Matlab里关于T2F/F2T/lpf.m函数调用应注意的问题及函数修改