责任链模式
1、行为型模式概述
- 行为型模式是对不同对象之间划分职责和算法的抽象化;
- 行为型模式注重于类或对象之间的协作,而不重视他们的结构;
- 行为型模式可以很好的划分类和对象之间的责任,并在系统运行中研究他们之间的协作交互,已完成负责的功能;
- 行为型模式分为类行为型模式和对象行为型模式;
a. 类行为型模式主要通过继承来分配父类及其子类间的责任,利用的是多态;
b. 对象行为型模式主要通过关联聚合来分配对象间的责任,根据“合成复用原则”,系统中要尽量使用关联关系来取代继承关系,因此大部分行为型设计模式都属于对象行为型设计模式。
2、责任链模式的动机
- 请求与处理进行解耦,将请求处理组织成一条线,依次对请求进行处理,请求者只需要把请求发送到请求处理链中即可,而不 关注是谁处理这个请求;
- 责任链即处理链可以是一个环,一条直线,也可以是一棵树,常见的是一条线;
3、责任链模式的定义
避免请求和处理耦合在一起,将多个处理对象串联起来,并沿着这条线传递请求,直到请求处理完成返回为止;
4、责任链模式的类结构图
模式中包含三个角色:抽象处理类(接口或者抽象类),具体处理类,客户端;
- 多个对象由上一个对象对其下家的引用进行串联;
- 请求在链上进行传递,知道处理完成为止;
- 客户端不知道请求在哪里请求终止,因此系统可以对责任链进行重新组装和分配,符合开放封闭原则;
5、 优缺点和适用场景
优点:
- 降低耦合度
- 可简化对象的相互连接
- 增强给对象指派职责的灵活性
- 增加新的请求处理类很方便
缺点:
- 不能保证请求一定被接收。
- 系统性能将受到一定影响,而且在进行代码调试时不太方便;可能会造成循环调用。
适用场景:
- 多个对象处理请求,具体哪个对象处理请求由运行时决定;
- 在不明确哪个对象接受请求,向多个处理对象中提出一个请求;
- 可动态的指定一组处理对象;
6、实例
6.1
例1:餐费申请,先通过项目组长审批,若项目组长没权限,则由经理审批;
说明:改责任链的通过上家对下家的引用进行串联起来的,即依赖对象间的聚合;
a、定义接口
public abstract class Handler {
private Handler success;
public Handler getSuccess() {
return success;
}
public void setSuccess(Handler success) {
this.success = success;
}
public abstract String handle(String user, double fee);
}
b、实现具体处理类
public class ProjectHandler extends Handler {
public String handle(String user, double fee) {
if (fee < 500) {
if ("张三".equals(user)) {
return "同意" + user + "报销餐费" + fee;
} else {
return "不统一同意" + user + "报销餐费" + fee;
}
}
if (getSuccess() != null) {
return getSuccess().handle(user, fee);
}
return null;
}
}
public class ManageHandler extends Handler {
public String handle(String user, double fee) {
if (fee > 500) {
if ("李四".equals(user)) {
return "同意" + user + "报销餐费" + fee;
} else {
return "不统一同意" + user + "报销餐费" + fee;
}
}
if (getSuccess() != null) {
return getSuccess().handle(user, fee);
}
return null;
}
}
c、客户端调用
public class TestHandler {
public static void main(String[] args) {
Handler projectHandler = new ProjectHandler();
Handler manageHandler = new ManageHandler();
projectHandler.setSuccess(manageHandler);
String msg = projectHandler.handle("李四", 400);
System.out.println(msg);
}
}
例2:由多个对象过滤掉消息中的铭感字符串
注意:该责任链主要通过对象间的依赖进行串联起来的,
强烈建议使用这种方法进行串联
a、定义接口
public interface Filter {
String doFilter(String msg, ChainFilter chainFilter);
}
b、实现具体处理类
public class HTMLFilter implements Filter {
public String doFilter(String msg, ChainFilter chainFilter) {
System.out.println("HTMLFilter.doFilter");
msg = msg.replace("zy", "张三");
return chainFilter.doFilter(msg,chainFilter);
}
}
public class MessageFilter implements Filter {
public String doFilter(String msg, ChainFilter chainFilter) {
System.out.println("HTMLFilter.doFilter");
msg=msg.replace("mm", "李四");
return chainFilter.doFilter(msg,chainFilter);
}
}
c、实例串联类
public class ChainFilter implements Filter {
private List<Filter> chainFilter=new ArrayList<Filter>();
private int index;
public String doFilter(String msg, ChainFilter chainFilter) {
if (index == this.chainFilter.size()) {
return msg;
}
Filter filter1 = this.chainFilter.get(index);
index++;
return filter1.doFilter(msg,chainFilter);
}
public void addFilter(Filter filter) {
chainFilter.add(filter);
}
}
d、客户端的调用
public class Client {
public static void main(String[] args) {
String msg="zymm";
ChainFilter chainFilter = new ChainFilter();
chainFilter.addFilter(new HTMLFilter());
chainFilter.addFilter(new MessageFilter());
msg=chainFilter.doFilter(msg,chainFilter);
System.out.println(msg);
}
}
以上串联方式主要通过ChainFilter进行处理类的串联,取出一个处理对象,处理对象处理请求,然后在到串联对象中,由串联对象再取 一个处理对象,处理请求,依次进行下去;
- 上一篇 mybatis一次会话源码解析
- 下一篇 观察者模式