行为型模式之责任链模式
2019-03-07 本文已影响0人
BrotherTree
在设计模式中,责任链模式是属于行为模式,请求从一个起点开始,沿着任务链依次传递给下一个节点,直到某个节点处理了该请求而结束。
责任链中的每个节点都有机会去处理该请求,且发送方不需要关心接收方(链)的结构,这样就有效的避免了发送者和接收者之间的耦合。
在Android中,Touch事件分发流程就是典型的责任链模式,事件沿着Activity、ViewGroup和View传递,直到其中某一方消费了该事件为止。
image.png
举个栗子
公司员工级别:普通员工、部门经理、总经理、老板
普通员工需要请假,2天需要部门经理批准,5天需要总经理批准,10天需要老板批准。
首先,编写员工类
public class Staff {
// 员工需要请假天数所在level
// 1:10天以内,此时需Boss批准
// 2:5天以内,此时需GeneralManager批准
// 3:2天以内,此时需OrdinaryManager批准
// 其他:谁也不会批准
private int level;
// 请假描述
private String request;
public Staff(int level) {
this.level = level;
switch (this.level) {
case 1:
this.request = "员工请假10天以内";
break;
case 2:
this.request = "员工请假5天以内";
break;
case 3:
this.request = "员工请假2天以内";
break;
default:
this.request = "员工请假超过10天";
break;
}
}
// 获取员工需要请假天数所在level
public int getLevel() {
return level;
}
// 请假描述
public String getRequest() {
return request;
}
}
编写Manger类,此类是一个抽象类
public abstract class Manager {
// 员工等级
public static final int BOSS = 1;// 老板
public static final int GENERAL_MANAGER = 2;// 总经理
public static final int ORDINARY_MANAGER = 3;// 部门经理
private int level;
private Manager nextManger;
public Manager(int level) {
this.level = level;
}
// 设置下一个处理节点
public void setNextManger(Manager nextManger) {
this.nextManger = nextManger;
}
public final void request(Staff staff) {
// 获取请假等级和当前manager等级进行比较,如果相等,则当前manager有权限批准
if (staff.getLevel() == level) {
// 调用子类manager的处理
response(staff);
} else {
// 如果nextManger不为null,即存在下一个处理节点
if (nextManger != null) {
// 下一个处理节点来处理该请求,这里使用了递归调用
nextManger.request(staff);
} else {
// 没有下一个处理者
System.out.println("项目紧张,无法批准这么多天假期");
System.out.println("==========================");
}
}
}
// 抽象方法,需要子类实现
protected abstract void response(Staff staff);
}
下面是实现三个Manger的子类
// 老板
public class Boss extends Manager {
public Boss() {
super(Manager.BOSS);
}
// 处理请求
@Override
protected void response(Staff staff) {
System.out.println("员工问Boss");
System.out.println(staff.getRequest());
System.out.println("Boss回答OK");
System.out.println("==========================");
}
}
// 总经理
public class GeneralManager extends Manager {
public GeneralManager() {
super(Manager.GENERAL_MANAGER);
}
// 处理请求
@Override
protected void response(Staff staff) {
System.out.println("员工问GeneralManager");
System.out.println(staff.getRequest());
System.out.println("GeneralManager回答OK");
System.out.println("==========================");
}
}
// 部门经理
public class OrdinaryManager extends Manager {
public OrdinaryManager() {
super(Manager.ORDINARY_MANAGER);
}
// 处理请求
@Override
protected void response(Staff staff) {
System.out.println("员工问OrdinaryManager");
System.out.println(staff.getRequest());
System.out.println("OrdinaryManager回答OK");
System.out.println("==========================");
}
}
最后是发起员工的请假事宜
public class TestMain {
public static void main(String[] args) {
// 1...4之间随机数,作为员工请假等级,对应manager的等级
Random random = new Random();
ArrayList<Staff> arrayList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
arrayList.add(new Staff(random.nextInt(4)));
}
// 三个manager对象
Manager ordinaryManager = new OrdinaryManager();
Manager generalManager = new GeneralManager();
Manager boss = new Boss();
// 设置责任链的下一个处理节点
// 部门经理之后是总经理
ordinaryManager.setNextManger(generalManager);
// 总经理之后是老板
generalManager.setNextManger(boss);
// 为了体现不同请假等级后的不同处理情况,这里用一个数组来产生多个请求
for (Staff staff : arrayList) {
// 开始第一个节点的请求
ordinaryManager.request(staff);
}
}
}
执行结果(随机)
员工问OrdinaryManager
员工请假2天以内
OrdinaryManager回答OK
==========================
员工问OrdinaryManager
员工请假2天以内
OrdinaryManager回答OK
==========================
员工问OrdinaryManager
员工请假2天以内
OrdinaryManager回答OK
==========================
员工问GeneralManager
员工请假5天以内
GeneralManager回答OK
==========================
员工问OrdinaryManager
员工请假2天以内
OrdinaryManager回答OK
==========================
员工问OrdinaryManager
员工请假2天以内
OrdinaryManager回答OK
==========================
员工问OrdinaryManager
员工请假2天以内
OrdinaryManager回答OK
==========================
项目紧张,无法批准这么多天假期
==========================
员工问GeneralManager
员工请假5天以内
GeneralManager回答OK
==========================
项目紧张,无法批准这么多天假期
==========================
Process finished with exit code 0
image.png
角色分析
- Manager:抽象处理者角色,声明一个处理请求的方法,并保持对下一个处理节点Manager对象的引用
- Boss:具体的处理者,对请求进行处理,如果不处理就讲请求转发给下一个节点上的处理对象(GeneralManager、OrdinaryManager同Boss)
优点
- 降低耦合度,将请求的发送者和接收者解耦,便于拓展,提高代码灵活性。
- 简化了对象。使得对象不需要知道链的结构。
- 增强给对象指派责任节点的灵活性,通过改变链内的成员或者调动它们的次 序,允许动态地新增或者删除责任节点。
缺点
- 如果责任链太长,或者每条链判断处理的时间太长会影响性能。特别是递归循环的时候。
- 请求不一定能得到处理,可能会没有对象处理。