責(zé)任鏈模式
顧名思義,責(zé)任鏈模式(Chain of Responsibility Pattern)為請(qǐng)求創(chuàng)建了一個(gè)接收者對(duì)象的鏈规揪。這種模式給予請(qǐng)求的類型,對(duì)請(qǐng)求的發(fā)送者和接收者進(jìn)行解耦。這種類型的設(shè)計(jì)模式屬于行為型模式。
在這種模式中巍虫,通常每個(gè)接收者都包含對(duì)另一個(gè)接收者的引用。如果一個(gè)對(duì)象不能處理該請(qǐng)求鳍刷,那么它會(huì)把相同的請(qǐng)求傳給下一個(gè)接收者占遥,依此類推。
介紹
意圖:避免請(qǐng)求發(fā)送者與接收者耦合在一起倾剿,讓多個(gè)對(duì)象都有可能接收請(qǐng)求筷频,將這些對(duì)象連接成一條鏈,并且沿著這條鏈傳遞請(qǐng)求前痘,直到有對(duì)象處理它為止。
主要解決:職責(zé)鏈上的處理者負(fù)責(zé)處理請(qǐng)求担忧,客戶只需要將請(qǐng)求發(fā)送到職責(zé)鏈上即可芹缔,無須關(guān)心請(qǐng)求的處理細(xì)節(jié)和請(qǐng)求的傳遞,所以職責(zé)鏈將請(qǐng)求的發(fā)送者和請(qǐng)求的處理者解耦了瓶盛。
何時(shí)使用:在處理消息的時(shí)候以過濾很多道最欠。
如何解決:攔截的類都實(shí)現(xiàn)統(tǒng)一接口。
關(guān)鍵代碼:Handler 里面聚合它自己惩猫,在 HanleRequest 里判斷是否合適芝硬,如果沒達(dá)到條件則向下傳遞,向誰傳遞之前 set 進(jìn)去轧房。
應(yīng)用實(shí)例:
1拌阴、紅樓夢(mèng)中的"擊鼓傳花"。
2奶镶、JS 中的事件冒泡迟赃。
3陪拘、JAVA WEB 中 Apache Tomcat 對(duì) Encoding 的處理,Struts2 的攔截器纤壁,jsp servlet 的 Filter左刽。
優(yōu)點(diǎn):
1、降低耦合度酌媒。它將請(qǐng)求的發(fā)送者和接收者解耦欠痴。
2、簡(jiǎn)化了對(duì)象秒咨。使得對(duì)象不需要知道鏈的結(jié)構(gòu)斋否。
3、增強(qiáng)給對(duì)象指派職責(zé)的靈活性拭荤。通過改變鏈內(nèi)的成員或者調(diào)動(dòng)它們的次序茵臭,允許動(dòng)態(tài)地新增或者刪除責(zé)任。
4舅世、增加新的請(qǐng)求處理類很方便旦委。
缺點(diǎn):
1、不能保證請(qǐng)求一定被接收雏亚。
2缨硝、系統(tǒng)性能將受到一定影響,而且在進(jìn)行代碼調(diào)試時(shí)不太方便罢低,可能會(huì)造成循環(huán)調(diào)用查辩。
3、可能不容易觀察運(yùn)行時(shí)的特征网持,有礙于除錯(cuò)宜岛。
使用場(chǎng)景:
1、有多個(gè)對(duì)象可以處理同一個(gè)請(qǐng)求功舀,具體哪個(gè)對(duì)象處理該請(qǐng)求由運(yùn)行時(shí)刻自動(dòng)確定萍倡。
2、在不明確指定接收者的情況下辟汰,向多個(gè)對(duì)象中的一個(gè)提交一個(gè)請(qǐng)求列敲。
3、可動(dòng)態(tài)指定一組對(duì)象處理請(qǐng)求帖汞。
注意事項(xiàng):在 JAVA WEB 中遇到很多應(yīng)用戴而。
實(shí)現(xiàn)
我們創(chuàng)建抽象類 AbstractLogger,帶有詳細(xì)的日志記錄級(jí)別翩蘸。然后我們創(chuàng)建三種類型的記錄器所意,都擴(kuò)展了 AbstractLogger。每個(gè)記錄器消息的級(jí)別是否屬于自己的級(jí)別,如果是則相應(yīng)地打印出來扁眯,否則將不打印并把消息傳給下一個(gè)記錄器壮莹。
步驟 1
創(chuàng)建抽象的記錄器類。AbstractLogger.java
public abstract class AbstractLogger {
public static int INFO = 1;
public static int DEBUG = 2;
public static int ERROR = 3;
protected int level; // 責(zé)任鏈中的下一個(gè)元素
protected AbstractLogger nextLogger;
public void setNextLogger(AbstractLogger nextLogger) {
this.nextLogger = nextLogger;
}
public void logMessage(int level, String message) {
if (this.level <= level) {
write(message);
}
if (nextLogger != null) {
nextLogger.logMessage(level, message);
}
}
abstract protected void write(String message);
}
步驟 2
創(chuàng)建擴(kuò)展了該記錄器類的實(shí)體類姻檀。ConsoleLogger.java ErrorLogger.java FileLogger.java
public class ConsoleLogger extends AbstractLogger {
public ConsoleLogger(int level) {
this.level = level;
}
@Override
protected void write(String message) {
System.out.println("Standard Console::Logger: " + message);
}
}
public class ErrorLogger extends AbstractLogger {
public ErrorLogger(int level) {
this.level = level;
}
@Override
protected void write(String message) {
System.out.println("Error Console::Logger: " + message);
}
}
public class FileLogger extends AbstractLogger {
public FileLogger(int level) {
this.level = level;
}
@Override
protected void write(String message) {
System.out.println("File::Logger: " + message);
}
}
步驟 3
創(chuàng)建不同類型的記錄器命满。賦予它們不同的錯(cuò)誤級(jí)別,并在每個(gè)記錄器中設(shè)置下一個(gè)記錄器绣版。每個(gè)記錄器中的下一個(gè)記錄器代表的是鏈的一部分胶台。ChainPatternDemo.java
public class ChainPatternDemo {
private static AbstractLogger getChainOfLoggers() {
AbstractLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR);
AbstractLogger fileLogger = new FileLogger(AbstractLogger.DEBUG);
AbstractLogger consoleLogger = new ConsoleLogger(AbstractLogger.INFO);
errorLogger.setNextLogger(fileLogger);
fileLogger.setNextLogger(consoleLogger);
return errorLogger;
}
public static void main(String[] args) {
AbstractLogger loggerChain = getChainOfLoggers();
loggerChain.logMessage(AbstractLogger.INFO, "This is an information.");
loggerChain.logMessage(AbstractLogger.DEBUG, "This is an debug level information.");
loggerChain.logMessage(AbstractLogger.ERROR, "This is an error information.");
}
}
步驟 4
執(zhí)行程序,輸出結(jié)果:
Standard Console::Logger: This is an information. File::Logger: This is an debug level information. Standard Console::Logger: This is an debug level information. Error Console::Logger: This is an error information. File::Logger: This is an error information. Standard Console::Logger: This is an error information.