BrightLoong's Blog

设计模式——职责链模式

chain

一. 概述

职责链模式(Chain of Responsibility):使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止(个人认为并不一定非要满足这种情况,也可以是每个对象可以处理请求的一部分,或者是下一个处理对象需要上一个处理对象首先完成一些工作,将请求沿链一步一步传递,知道请求最终处理完成,既同时兼顾请求处理和请求转发,当然这个仅仅是个人理解,可能不正确,还请谅解)。

使用职责链模式,发起请求的客户端并不用知道是链中的哪一个对象最终处理了这个请求,所以这样系统的更改可以在不影响客户端的情况下动态地重新组织和分配责任。

职责链模式属于行为型模式。

二. UML类图解析

职责链模式的UML类图如下:

chain

  • Handler:处理请求的抽象类,持有一个Handler引用作为后继者,setSuccessor(Handler handler)用于设置后继者;handleRequest(Request request)是处理请求的抽象方法,Request是具体的请求,按照自己的需求定义,可以简单的基本类型,集合类,也可以是自定义的类,等待子类具体实现。
  • ConcreteHandler1、ConcreteHandler2:具体处理者类,处理客户端请求,也可以访问后继者,按照职责链模式的定义,要么处理请求,要么转发请求,不存在两者同时兼顾的行为。

三. 代码实现

用向银行贷款作为例子,申请的贷款金额不同需要不同等级的银行人员进行授权。

贷款请求类——LoanRequest

首先创建一个贷款请求,具有基本的贷款金额和贷款人信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package io.github.brightloong.design.chain;

/**
* 贷款请求类
* Created by BrightLoong on 2018/5/17.
*/
public class LoanRequest {
/**贷款金额*/
private Long loanAmount;

/**贷款人姓名*/
private String name;

/**
* 构造函数.
* @param loanAmount
* @param name
*/
public LoanRequest(Long loanAmount, String name) {
this.loanAmount = loanAmount;
this.name = name;
}

public Long getLoanAmount() {
return loanAmount;
}

public void setLoanAmount(Long loanAmount) {
this.loanAmount = loanAmount;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}

抽象处理接口——BankStaff

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package io.github.brightloong.design.chain;

/**
* 请求处理抽象类.
* Created by BrightLoong on 2018/5/17.
*/
public abstract class BankStaff {

/**持有的后继者的引用*/
private BankStaff nextBankStaff;

/**设置后继者*/
public void setNextBankStaff(BankStaff bankStaff) {
this.nextBankStaff = bankStaff;
}

/**获取后继者*/
public BankStaff getNextBankStaff() {
return this.nextBankStaff;
}

/**抽象处理方法,等待子类实现*/
public abstract void handleLoan(LoanRequest request);
}

银行柜员实现——BankTeller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package io.github.brightloong.design.chain;

/**
* Created by BrightLoong on 2018/5/17.
*/
public class BankTeller extends BankStaff {
public void handleLoan(LoanRequest request) {
if (request.getLoanAmount() <= 20000) {
System.out.println(request.getName() + "申请贷款:" + request.getLoanAmount() + "元," + "由银行柜员处理。" );
} else if (getNextBankStaff() != null) {
getNextBankStaff().handleLoan(request);
} else {
System.out.println("无法处理的贷款请求。");
}
}
}

银行经理实现——BankManager

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package io.github.brightloong.design.chain;

/**
* Created by BrightLoong on 2018/5/17.
*/
public class BankManager extends BankStaff{
public void handleLoan(LoanRequest request) {
if (request.getLoanAmount() <= 100000) {
System.out.println(request.getName() + "申请贷款:" + request.getLoanAmount() + "元," + "由银行经理处理。" );
} else if (getNextBankStaff() != null) {
getNextBankStaff().handleLoan(request);
} else {
System.out.println("无法处理的贷款请求。");
}
}
}

银行行长实现——BankPresident

1
2
3
4
5
6
7
8
9
10
package io.github.brightloong.design.chain;

/**
* Created by BrightLoong on 2018/5/17.
*/
public class BankPresident extends BankStaff {
public void handleLoan(LoanRequest request) {
System.out.println(request.getName() + "申请贷款:" + request.getLoanAmount() + "元," + "由银行行长处理。" );
}
}

客户端调用和输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package io.github.brightloong.design.chain;

/**
* Created by BrightLoong on 2018/5/17.
*/
public class Client {
public static void main(String[] args) {
//构造职责链
BankStaff bankTeller = new BankTeller();
BankStaff bankManager = new BankManager();
BankStaff bankPresident = new BankPresident();
bankTeller.setNextBankStaff(bankManager);
bankManager.setNextBankStaff(bankPresident);

//构造请求
LoanRequest request = new LoanRequest(10000L, "小明");
bankTeller.handleLoan(request);

LoanRequest request2 = new LoanRequest(200000L, "老王");
bankTeller.handleLoan(request2);
}
}

输出结果:

1
2
小明申请贷款:10000元,由银行柜员处理。
老王申请贷款:200000元,由银行行长处理。

四. 总结

使用场景

  • 有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。
  • 在不明确接收者的情况下,向多个对象中的一个处理提交一个请求。
  • 可动态指定一组对象处理请求。

优点

  • 实现了请求发送者和接收者的解耦,降低了耦合度。
  • 方便扩展,可以方便的增加请求处理类。
  • 可以动态的设置请求处理类的顺序,比较灵活。
  • 接收者和发送者都没有对方的明确信息,且链中的对象自己也并不知道链的结构。结果是职责链可简化对象的相互连接,它们仅需要保持一个指向后继者的引用。

缺点

  • 请求有可能到了链的末端都得不到处理,或者因为没有正确配置而得不到处理。
  • 如果要配置比较复杂的链会导致性能受到影响,并且难于调试,易于出错

参考:http://www.runoob.com/design-pattern/chain-of-responsibility-pattern.html

坚持原创技术分享,您的支持将鼓励我继续创作!