學(xué)習(xí)《Android 源碼設(shè)計模式解析與實踐》系列筆記
介紹
所謂的鏈,是指將多個節(jié)點首尾相連形成的結(jié)構(gòu)泣特。
編程中的責(zé)任鏈模式,類似于這種結(jié)構(gòu)挑随,將每個節(jié)點看作是一個對象,每個對象擁有不同的處理邏輯兜挨,將一個請求從鏈?zhǔn)降氖锥税l(fā)出,沿著鏈的路徑一次傳遞拌汇,直到有對象處理這個請求為止,我們將這樣的模式稱為責(zé)任鏈模式噪舀。
責(zé)任鏈模式屬于行為型設(shè)計模式魁淳。
定義
使多個對象都有機(jī)會處理請求,從而避免了請求的發(fā)送者和接受者之間的耦合關(guān)系界逛。將這些對象連成一條鏈,并沿這條鏈傳遞請求息拜,直到有對象處理它為止溉潭。
使用場景
- 多個對象可以處理同一請求,但具體由哪個對象處理則在運(yùn)行時動態(tài)決定少欺。
- 在請求處理者不明確的情況下向多個對象中的一個提交一個請求喳瓣。
- 需要動態(tài)指定一組對象處理請求。
結(jié)構(gòu)
1 簡單版的責(zé)任鏈模式結(jié)構(gòu)
- Handler : 抽象處理者對象狈茉,聲明一個請求處理的方法夫椭,并持有下一個處理節(jié)點 Handler 對象的引用。
- ConcreteHandler : 具體處理者角色氯庆,對請求進(jìn)行處理蹭秋,不能處理的則將請求傳遞給下一個節(jié)點的處理者。
簡單示例
/**
* 抽象處理者
*/
public abstract class Handler {
protected Handler mSuccessor;
public void setSuccessor(Handler successor) {
mSuccessor = successor;
}
public abstract void handleRequest(String condition);
}
/**
* 具體的處理者堤撵,ConcreteHandler1
*/
public class ConcreteHandler1 extends Handler {
@Override
public void handleRequest(String condition) {
if (condition.equals("ConcreteHandler1")) {
System.out.println("ConcreteHandler1 handled");
} else {
mSuccessor.handleRequest(condition);
}
}
}
/**
* 具體的處理者仁讨,ConcreteHandler2
*/
public class ConcreteHandler2 extends Handler {
@Override
public void handleRequest(String condition) {
if (condition.equals("ConcreteHandler2")) {
System.out.println("ConcreteHandler2 handled");
} else {
mSuccessor.handleRequest(condition);
}
}
}
/**
* 具體的處理者,ConcreteHandler3
*/
public class ConcreteHandler3 extends Handler {
@Override
public void handleRequest(String condition) {
if (condition.equals("ConcreteHandler3")) {
System.out.println("ConcreteHandler3 handled");
} else {
mSuccessor.handleRequest(condition);
}
}
}
public class Client {
public static void main(String args[]) {
Handler handler1 = new ConcreteHandler1();
Handler handler2 = new ConcreteHandler2();
Handler handler3 = new ConcreteHandler3();
handler1.mSuccessor = handler2;
handler2.mSuccessor = handler3;
//處理請求
handler1.handleRequest("ConcreteHandler3");
}
}
這里的請求是一個固定的 String
字符串实昨,但是在實際運(yùn)用中洞豁,可能請求的情況會比較復(fù)雜,所以這里的請求也可以抽出一個基類荒给,進(jìn)行封裝丈挟。
2 改進(jìn)的責(zé)任鏈模式結(jié)構(gòu)
這里增加了 level
,只有處理者和請求的級別一致時志电,才能處理該請求曙咽,不然就交由下一個節(jié)點的處理者處理該請求。
簡單示例
/**
* 抽象的請求
*/
public abstract class Request {
// 需要處理的內(nèi)容
private Object mContent;
public Request(Object content) {
mContent = content;
}
public Object getContent() {
return mContent;
}
public abstract int getRequestLevel();
}
/**
* 請求的具體實現(xiàn)類挑辆,ConcreteRequest1
*/
public class ConcreteRequest1 extends Request {
public ConcreteRequest1(Object content) {
super(content);
}
@Override
public int getRequestLevel() {
return 1;
}
}
/**
* 請求的具體實現(xiàn)類例朱,ConcreteRequest2
*/
public class ConcreteRequest2 extends Request {
public ConcreteRequest2(Object content) {
super(content);
}
@Override
public int getRequestLevel() {
return 2;
}
}
/**
* 請求的具體實現(xiàn)類,ConcreteRequest3
*/
public class ConcreteRequest3 extends Request {
public ConcreteRequest3(Object content) {
super(content);
}
@Override
public int getRequestLevel() {
return 3;
}
}
/**
* 抽象處理者
*/
public abstract class Handler {
protected Handler mSuccessor;
public void setSuccessor(Handler successor) {
mSuccessor = successor;
}
public void handleRequest(Request request) {
if (getHandlerLevel() == request.getRequestLevel()) {
handle(request);
} else {
mSuccessor.handleRequest(request);
}
}
public abstract int getHandlerLevel();
public abstract void handle(Request request);
}
/**
* 具體的處理者鱼蝉,ConcreteHandler1
*/
public class ConcreteHandler1 extends Handler {
@Override
public int getHandlerLevel() {
return 1;
}
@Override
public void handle(Request request) {
System.out.println("ConcreteHandler1 handled");
}
}
/**
* 具體的處理者洒嗤,ConcreteHandler2
*/
public class ConcreteHandler2 extends Handler {
@Override
public int getHandlerLevel() {
return 2;
}
@Override
public void handle(Request request) {
System.out.println("ConcreteHandler2 handled");
}
}
/**
* 具體的處理者,ConcreteHandler3
*/
public class ConcreteHandler3 extends Handler {
@Override
public int getHandlerLevel() {
return 3;
}
@Override
public void handle(Request request) {
System.out.println("ConcreteHandler3 handled");
}
}
/**
* Created by linpu on 2019/2/14 .
*/
public class Client {
public static void main(String args[]) {
Handler handler1 = new ConcreteHandler1();
Handler handler2 = new ConcreteHandler2();
Handler handler3 = new ConcreteHandler3();
handler1.mSuccessor = handler2;
handler2.mSuccessor = handler3;
Request request1 = new ConcreteRequest1("Requestq1");
Request request2 = new ConcreteRequest2("Requestq2");
Request request3 = new ConcreteRequest3("Requestq3");
//處理請求
handler1.handleRequest(request1);
handler1.handleRequest(request2);
handler1.handleRequest(request3);
}
}
實現(xiàn)
XX 需要申請五萬的經(jīng)費魁亦。于是他向他的上級渔隶,也就是項目組的組長提出申請,但是組長沒有權(quán)限審批這么大數(shù)目的經(jīng)費吉挣。于是派撕,組長找到部門主管婉弹,主管一看也超出了自己的權(quán)限。于是繼續(xù)找到上級的經(jīng)理终吼,經(jīng)理看了說他只能審批1萬以內(nèi)的數(shù)額镀赌,所以他拿著審批文件找到了老板。最后老板看了文件后批準(zhǔn)了际跪。
在整個申請過程中,申請人 XX 只和組長產(chǎn)生了關(guān)聯(lián)姆打,然后請求就層層的網(wǎng)上傳達(dá),他不關(guān)心中間的過程玛追,只關(guān)心最后的審批結(jié)果闲延。所以說,責(zé)任鏈很好的將請求的發(fā)起者和處理者進(jìn)行了解耦陆馁。
具體代碼如下:
/**
* 抽象領(lǐng)導(dǎo)者類
*/
public abstract class Leader {
protected Leader mAccessor;
public void handleRequest(int money) {
if (money <= limit()) {
handler(money);
} else {
if (mAccessor != null) {
mAccessor.handleRequest(money);
}
}
}
// 最高能批復(fù)的額度
public abstract int limit();
public abstract void handler(int money);
}
/**
* 組長類
*/
public class GroupLeader extends Leader {
@Override
public int limit() {
return 1000;
}
@Override
public void handler(int money) {
System.out.println("組長批復(fù)報銷:" + money + " 元");
}
}
/**
* 主管類
*/
public class Director extends Leader {
@Override
public int limit() {
return 5000;
}
@Override
public void handler(int money) {
System.out.println("主管批復(fù)報銷:" + money + " 元");
}
}
/**
* 經(jīng)理類
*/
public class Manager extends Leader {
@Override
public int limit() {
return 10000;
}
@Override
public void handler(int money) {
System.out.println("經(jīng)理批復(fù)報銷:" + money + " 元");
}
}
/**
* 老板類
*/
public class Boss extends Leader {
@Override
public int limit() {
return Integer.MAX_VALUE;
}
@Override
public void handler(int money) {
System.out.println("老板批復(fù)報銷:" + money + " 元");
}
}
/**
* 發(fā)起請求的職員
*/
public class Staff {
public static void main(String args[]) {
Leader groupLeader = new GroupLeader();
Leader director = new Director();
Leader manager = new Manager();
Leader boss = new Boss();
groupLeader.mAccessor = director;
director.mAccessor = manager;
manager.mAccessor = boss;
//想組長發(fā)起申請
groupLeader.handleRequest(50000);
}
}
結(jié)果:
老板批復(fù)報銷:50000 元
總結(jié)
優(yōu)點:
對請求者和處理者進(jìn)行了解耦叮贩,提高代碼的靈活性佛析。
缺點:
需要對鏈進(jìn)行遍歷,如果處理者很多寸莫,那整個遍歷的時間可能就很長,可能會影響性能。
相關(guān)文章:
設(shè)計模式整理(1) 代理模式
設(shè)計模式整理(2) 單例模式
設(shè)計模式整理(3) Builder 模式
設(shè)計模式整理(4) 原型模式
設(shè)計模式整理(5) 工廠模式
設(shè)計模式整理(6) 策略模式
設(shè)計模式整理(7) 狀態(tài)模式
設(shè)計模式整理(8) 責(zé)任鏈模式
設(shè)計模式整理(9) 觀察者模式
設(shè)計模式整理(10) 適配器模式
設(shè)計模式整理(11) 裝飾模式
設(shè)計模式整理(12) 中介者模式