Fork me on GitHub

设计模式之责任链模式

设计模式之责任链模式

1. 什么是责任链模式

Chain of Responsibility(CoR)模式也叫职责链模式或者责任链模式,是行为模式之一,该模式构造一系列分别担当不同的职责的类的对象来共同完成一个任务,这些类的对象之间像链条一样紧密相连,所以被称作职责链模式。

换句话说责任链模式就是如果有多个对象都有机会处理请求,责任链可使请求的发送者和接收者解耦,请求沿着责任链传递,直到有一个对象处理了它为止。

责任链模式的结构:

1

要实现Chain of Responsibility模式,需要满足该模式的基本条件

  1. 对象链的组织。需要将某任务的所有职责执行对象以链的形式加以组织。
  2. 消息或请求的传递。将消息或请求沿着对象链传递,以让处于对象链中的对象得到处理机会。
  3. 处于对象链中的对象的职责分配。不同的对象完成不同的职责。
  4. 任务的完成。处于对象链的末尾的对象结束任务并停止消息或请求的继续传递。

优缺点

优点:

  • 将请求的发送者和接收者解耦,使多个对象都有机会处理这个请求
  • 可以简化对象,因为它无须知道链的结构
  • 可以动态地增加或删减处理请求的链结构

缺点:

  • 请求从链的开头进行遍历,对性能有一定的损耗
  • 并不保证请求一定被处理

适用场合

  • 有多个对象可以处理一个请求
  • 不明确接收者的情况,就是你把事情扔到责任链中,找一圈总能找到合适的处理者
  • 有序、无序链,线型、树形、环形链

举几个例子:

  • 例1:比如客户Client要完成一个任务,这个任务包括a,b,c,d四个部分。首先客户Client把任务交给A,A完成a部分之后,把任务交给B,B完成b部分,…,直到D完成d部分。
  • 例2:比如政府部分的某项工作,县政府先完成自己能处理的部分,不能处理的部分交给省政府,省政府再完成自己职责范围内的部分,不能处理的部分交给中央政府,中央政府最后完成该项工作。
  • 例3:软件窗口的消息传播。
  • 例4:SERVLET容器的过滤器(Filter)框架实现。

2. 具体实例:

从一个具体的实例来简单看下责任链模式是怎么实现和使用的。

购买请求决策项目:

决策因素:价格

决策级别:组长、部长、副总、总裁

我们一般就是想设计一个抽象类,然后使用switch实现决策的功能,然后具体的实现和处理由下面的具体的继承和扩展的类来做。这样做的时候就是我们要个更改决策者的权限或者是增加删除决策者的时候需要将这个抽象类一并修改,不符合开闭的原则。

然后我们这里用责任链模式进行的设计如下所示:

类图:

2

其实就是把switch的决策交给了责任链去实现。每一层的具体的去做,到能够处理掉的时候就把事情处理掉,否则往下一层找。

具体的代码:

结合上面的责任链的结构,我们需要有一个handler,在这里也就是Approver。

1
2
3
4
5
6
7
8
9
10
11
12
13
public abstract class Approver {
Approver successor;
String Name;
public Approver(String Name)
{
this.Name=Name;
}
public abstract void ProcessRequest( PurchaseRequest request);
public void SetSuccessor(Approver successor) {
// TODO Auto-generated method stub
this.successor=successor;
}
}

然后是具体的approver,也就是具体决策的执行者。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class DepartmentApprover extends Approver {

public DepartmentApprover(String Name) {
super(Name + " DepartmentLeader");

}

@Override
public void ProcessRequest(PurchaseRequest request) {
// TODO Auto-generated method stub

if ((5000 <= request.GetSum()) && (request.GetSum() < 10000)) {
System.out.println("**This request " + request.GetID()
+ " will be handled by " + this.Name + " **");
} else {
successor.ProcessRequest(request);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class GroupApprover extends Approver {

public GroupApprover(String Name) {
super(Name+" GroupLeader");
// TODO Auto-generated constructor stub

}

@Override
public void ProcessRequest(PurchaseRequest request) {
// TODO Auto-generated method stub

if (request.GetSum() < 5000) {
System.out.println("**This request " + request.GetID()
+ " will be handled by "
+ this.Name + " **");
} else {
successor.ProcessRequest(request);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class PresidentApprover extends Approver {

public PresidentApprover(String Name) {
super(Name + " President");

}

@Override
public void ProcessRequest(PurchaseRequest request) {
// TODO Auto-generated method stub
if (50000 <= request.GetSum()) {
System.out.println("**This request " + request.GetID()
+ " will be handled by " + this.Name + " **");
}else {
successor.ProcessRequest(request);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class VicePresidentApprover extends Approver {

public VicePresidentApprover(String Name) {
super(Name + " Vice President");
}

@Override
public void ProcessRequest(PurchaseRequest request) {
// TODO Auto-generated method stub
if ((10000 <= request.GetSum()) && (request.GetSum() < 50000)) {
System.out.println("**This request " + request.GetID()
+ " will be handled by " + this.Name + " **");
} else {
successor.ProcessRequest(request);
}
}

}

然后我们需要client也就是员工来发出请求:

Client:

1
2
3
4
5
6
7
8
public class Client {
public Client() {
}

public PurchaseRequest sendRequst(int Type, int Number, float Price) {
return new PurchaseRequest(Type, Number, Price);
}
}

请求:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class PurchaseRequest {
private int Type = 0;
private int Number = 0;
private float Price = 0;
private int ID = 0;

public PurchaseRequest(int Type, int Number, float Price) {
this.Type = Type;
this.Number = Number;
this.Price = Price;
}

public int GetType() {
return Type;
}

public float GetSum() {
return Number * Price;
}

public int GetID() {
return (int) (Math.random() * 1000);
}
}

这样整个的结构代码就完成了,测试类,在测试类中需要将所有的具体的Approver实例化,然后去一层一层的往下找,其实这里的话其实责任链已经构成了一个环,所以你具体的以哪一个Approver开始执行命令是不影响结果的。然后设计的责任链的顺序也是无所谓的,因为总会找到合适的处理者,但是这样也造成了性能的开销。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class MainTest {
public static void main(String[] args) {

Client mClient=new Client();
Approver GroupLeader=new GroupApprover("Tom");
Approver DepartmentLeader=new DepartmentApprover("Jerry");
Approver VicePresident=new VicePresidentApprover("Kate");
Approver President=new PresidentApprover("Bush");

GroupLeader.SetSuccessor(VicePresident);
DepartmentLeader.SetSuccessor(President);
VicePresident.SetSuccessor(DepartmentLeader);
President.SetSuccessor(GroupLeader);

VicePresident.ProcessRequest(mClient.sendRequst(1, 100, 40));
VicePresident.ProcessRequest(mClient.sendRequst(2, 200, 40));
VicePresident.ProcessRequest(mClient.sendRequst(3, 300, 40));
VicePresident.ProcessRequest(mClient.sendRequst(4, 400, 140));

}
}

3. 责任链模式与状态模式的差异

责任链模式和状态模式主要区别:

  • 责任链模式注重请求的传递
  • 状态模式注重对象状态的转换

本文标题:设计模式之责任链模式

文章作者:WilsonSong

发布时间:2018年10月17日 - 08:10

最后更新:2018年10月17日 - 08:10

原始链接:https://songwell1024.github.io/2018/10/17/ChainmsPattern/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

-------------本文结束感谢您的阅读-------------