原理或定義
是一种对象的行为模式。在职责链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织链和分配责任。
结构
抽象处理者(Handler)角色:定义出一个处理请求的接口。如果需要,接口可以定义出一个方法,以设定和返回对下家的引用。这个角色通常由一个抽象类或接口实现。
具体处理者(ConcreteHandle)角色:具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问下家。;
類圖
案例与代码
本文使用购买请求决策项目作为示例
购买请求决策项目介绍
决策因素:价格
决策级别:组长、部长、副总、总裁
一般设计方案:
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);
}
public void ProcessRequest(){
if(GetSum>500){
System.out.println("**This request " + request.GetID()
+ " will be handled by Group **");
}else if(){
System.out.println("**This request " + request.GetID()
+ " will be handled by Department **");
}else if(){
....
}
}
}
public class MainTest {
public static void main(String[] args) {
PurchaseRequest request=new PurchaseRequest(1, 100, 40);
request.ProcessRequest();
}
}
通过if else 语句判断级别。
这样设计会破坏开闭原则,还会导致强耦合。
责任链模式设计方案:
类图:
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);
}
}
抽象处理者(Handler)角色:
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;
}
}
具体处理者(ConcreteHandle)角色 :
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);
}
}
}
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);
}
}
}
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);
}
}
}
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);
}
}
}
管理 / 测试类:
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));
}
}
如果有多个对象都有机会处理请求,责任链可使请求的发送者和接收者解耦,请求沿着责任链传递,直到有一个对象处理了它为止。
使用場景
1.多个对象可以处理同一请求,但具体由哪个对象处理则在运行时动态决定;
2.在请求处理着不明确的情况下向多个对象的一个提交一个请求;
3.需要动态指定一组对象处理请求
優缺點
主要优点有:
1. 请求者与处理者代码分离:降低了耦合度。
2.将请求的发送者和接收者解耦,使多个对象都有机会处理这个请求
3.可以简化对象,因为它无须知道链的结构
4.可以动态地增加或删减处理请求的链结构
缺点主要有:
责任链像一条链表一样,效率可能会有问题。不能保证请求一定被收到。