責(zé)任鏈?zhǔn)且环N日常開(kāi)發(fā)常用的設(shè)計(jì)模式,這里之所以說(shuō)它好用,是因?yàn)樨?zé)任鏈的形式很貼合面向過(guò)程的開(kāi)發(fā)思路,易于理解,同時(shí)鏈?zhǔn)揭怖陂_(kāi)發(fā)者歸納功能,管理代碼。
其實(shí)這種設(shè)計(jì)模式很容易理解,我們都知道鏈表(單向)的數(shù)據(jù)結(jié)構(gòu):
class Node {
private Node next;
private Object value;
……(構(gòu)造方法)
}
理解鏈表就很容易理解責(zé)任鏈:責(zé)任鏈?zhǔn)怯啥鄠€(gè)執(zhí)行對(duì)象構(gòu)成的,它們都有兩個(gè)共同的屬性:一是“next”,表示下一個(gè)執(zhí)行對(duì)象;二是執(zhí)行方法,也就是說(shuō)當(dāng)前對(duì)象需要進(jìn)行的操作方法。既然所有執(zhí)行對(duì)象都有這兩個(gè)共同的屬性,我們就可以抽象出一個(gè)抽象類,它有一個(gè)基礎(chǔ)屬性“next”,和抽象方法:“handleWork”:
public abstract class Handler {
protected Handler next;
abstract protected String handleWork(Object obj);
}
看起來(lái)Node和Handler可以對(duì)應(yīng)上,只是說(shuō)Node沒(méi)有具體的行為方法,而Handler有基礎(chǔ)方法。
有以上的基礎(chǔ)知識(shí),咱們來(lái)實(shí)現(xiàn)這樣一個(gè)場(chǎng)景:
咱們有一個(gè)收入證明需要申請(qǐng)公司蓋章,這個(gè)過(guò)程中需要小組領(lǐng)導(dǎo),部門主管,公司財(cái)務(wù)進(jìn)行審批。只有順次通過(guò)之后,才可以最終獲得公章。這里我們可以按照責(zé)任鏈的思路進(jìn)行實(shí)現(xiàn):
1. 創(chuàng)建證明的抽象類 Certification.java,雖然是個(gè)示例,但是我們還是按照真實(shí)設(shè)計(jì)出發(fā),證明的類型可能有很多,比如收入證明,結(jié)婚證明,核算證明等等,咱們抽象出一個(gè)證明類,然后創(chuàng)建它的子類IncomeCertification.java。
public abstract class Certification {
protected String name;
/**
* 1 - 收入證明
* 2 - 核算證明
* 3 - 結(jié)婚證明
*/
private Integer type;
private String owner;
//... get and set methods
}
public class IncomeCertification extends Certification {
private Integer income;
//... get and set methods
}
ok!entity定義完成,可以看到,收入證明有4個(gè)屬性,其中名稱、類型、擁有者是繼承自父類,具體收入是個(gè)性化屬性?,F(xiàn)在咱們定義責(zé)任鏈執(zhí)行對(duì)象的基類:
public abstract class Handler {
protected Handler next;
abstract protected boolean processCertification(Certification cert);
}
對(duì)于小組領(lǐng)導(dǎo)來(lái)說(shuō),他需要確認(rèn)該申請(qǐng)人屬于自己團(tuán)隊(duì):
public class GroupLeaderHandler extends Handler {
private static List<String> teamMember = new ArrayList<String>();
static {
teamMember.add("ruiruiyuzhi");
teamMember.add("zhangsan");
}
@Override
protected boolean processCertification(Certification cert) {
if (teamMember.contains(cert.getOwner())) {
return this.next.processCertification(cert);
}
return false;
}
}
對(duì)于部門領(lǐng)導(dǎo)來(lái)說(shuō),他需要確認(rèn)收入無(wú)誤:
public class DepartmentLeaderHandler extends Handler {
private static final Integer INCOME_TYPE = 1;
private static final Integer INCOME = 1000;
@Override
protected boolean processCertification(Certification cert) {
IncomeCertification incomeCert = (IncomeCertification) cert;
if (INCOME_TYPE.equals(cert.getType()) && INCOME.equals(incomeCert.getIncome())) {
return this.next.processCertification(cert);
}
return false;
}
}
財(cái)務(wù)人員判斷申請(qǐng)類型為已有類型,則審批通過(guò):
public class FinancialHandler extends Handler {
private static List<Integer> certType = new ArrayList<Integer>();
static {
certType.add(1);
certType.add(2);
certType.add(3);
}
@Override
protected boolean processCertification(Certification cert) {
return certType.contains(cert.getType());
}
}
到目前為止我們準(zhǔn)備好了各個(gè)責(zé)任鏈環(huán)節(jié)的執(zhí)行對(duì)象,進(jìn)而需要將其串成鏈,這個(gè)過(guò)程跟鏈表的初始化相似:
public static void main(String[] args) {
//1.初始化責(zé)任鏈
GroupLeaderHandler groupLeaderHandler = new GroupLeaderHandler();
DepartmentLeaderHandler departmentLeaderHandler = new DepartmentLeaderHandler();
FinancialHandler financialHandler = new FinancialHandler();
groupLeaderHandler.setNext(departmentLeaderHandler);
departmentLeaderHandler.setNext(financialHandler);
……
其次,構(gòu)建待審批的證明對(duì)象:
public static void main(String[] args) {
//1.初始化責(zé)任鏈
GroupLeaderHandler groupLeaderHandler = new GroupLeaderHandler();
DepartmentLeaderHandler departmentLeaderHandler = new DepartmentLeaderHandler();
FinancialHandler financialHandler = new FinancialHandler();
groupLeaderHandler.setNext(departmentLeaderHandler);
departmentLeaderHandler.setNext(financialHandler);
//2.構(gòu)建證明對(duì)象
IncomeCertification myIncomeCert = new IncomeCertification();
myIncomeCert.setIncome(1000);
myIncomeCert.setName("income certification");
myIncomeCert.setOwner("ruiruiyuzhi");
myIncomeCert.setType(1);
這時(shí)候我們就需要進(jìn)入責(zé)任鏈開(kāi)始審核了,但是入口在哪呢?當(dāng)然,你可以強(qiáng)行把GroupLeaderHandler中加入一個(gè)public方法,作為入口,但是這樣做擴(kuò)展性不好,比方說(shuō)這條審核的鏈條有新環(huán)節(jié)加入,或者有環(huán)節(jié)精簡(jiǎn),改變了入口,豈不是需要重新編寫入口?
其實(shí)我們可以把入口放在Handler中,這個(gè)方法意味著從當(dāng)前環(huán)節(jié)開(kāi)始,往下走,這樣我們只需要根據(jù)業(yè)務(wù)需要改變?nèi)肟趯?duì)象即可:
public abstract class Handler {
protected Handler next;
abstract protected boolean processCertification(Certification cert);
public Handler getNext() {
return next;
}
public void setNext(Handler next) {
this.next = next;
}
//從當(dāng)前結(jié)點(diǎn)開(kāi)始,往下走
public boolean processFromCurrentHandler(Certification cert) {
return this.processCertification(cert);
}
}
這樣,我們?cè)贛ain方法中去測(cè)試整個(gè)流程可以發(fā)現(xiàn),責(zé)任鏈的形式跑通了。
public class MainApplication {
public static void main(String[] args) {
GroupLeaderHandler groupLeaderHandler = new GroupLeaderHandler();
DepartmentLeaderHandler departmentLeaderHandler = new DepartmentLeaderHandler();
FinancialHandler financialHandler = new FinancialHandler();
groupLeaderHandler.setNext(departmentLeaderHandler);
departmentLeaderHandler.setNext(financialHandler);
IncomeCertification myIncomeCert = new IncomeCertification();
myIncomeCert.setIncome(1000);
myIncomeCert.setName("income certification");
myIncomeCert.setOwner("ruiruiyuzhi");
myIncomeCert.setType(1);
boolean isPass = groupLeaderHandler.processFromCurrentHandler(myIncomeCert);
if (isPass) {
System.out.println("get the certification");
} else {
System.out.println("reject");
}
}
}
