責(zé)任鏈(Chain of Responsibility)
[TOC]
定義
Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request.Chain the receiving objects and pass the request along the chain until an object handles it.(使多個(gè)對象都有機(jī)會處理請求术吝,從而避免了請求的發(fā)送者和接受者之間的耦合關(guān)系计济。將這些對象連成一條鏈,并沿著這條鏈傳遞該請求顿苇,直到有對象處理它為止峭咒。)
? 其實(shí)解釋也已經(jīng)非常明顯了,就是遵循單一職責(zé)來作為責(zé)任鏈的處理
接口纪岁,具體如何處理對象凑队,什么時(shí)候處理,誰來處理幔翰,則交由外部或者父類去實(shí)現(xiàn)漩氨,優(yōu)點(diǎn)
就是系統(tǒng)不需要考慮handler是如何分發(fā)和處理的,只需要提交待處理的事件即可遗增,不過缺點(diǎn)
也是顯而易見叫惊,鏈?zhǔn)絺鬟f會導(dǎo)致經(jīng)由的路徑非常長,每個(gè)責(zé)任鏈子類都會經(jīng)過做修,所以可以在封裝的時(shí)候考慮在合理的情況下對子鏈的數(shù)量進(jìn)行制約
簡單場景使用
還是老朋友LOL霍狰,在正常的比賽中,藍(lán)色方和紅色方都需要5位玩家進(jìn)行游戲饰及,而5位玩家中也有不同的職責(zé)蔗坯,中單,上單燎含,ADC和輔助以及打野爸爸宾濒,這里就用責(zé)任鏈的方式來實(shí)現(xiàn)玩家與玩家直接的對線輔助提示功能
coding
首先定義咱們的責(zé)任鏈接口
public interface IHandle {
enum LineType {
TOP,
MIDDLE,
ADC,
ASSIST,
DADDY,
OTHER
}
/**
* 能否處理此對線
*
* @param lineType 對線信息
* @return
*/
boolean canHandle(LineType lineType);
/**
* 下一任對線處理者
*
* @param handler
*/
void setNextHandler(IHandle handler);
/**
* 處理對線
*
* @param lineType 對線信息
* @return
*/
String handle(LineType lineType);
}
接下來定義處理對線信息的基類,負(fù)責(zé)調(diào)度邏輯和約束子類存在
public abstract class BaseHandler implements IHandle {
protected IHandle mNextHandler;
@Override
public final String handle(LineType lineType) {
if (canHandle(lineType)) {
return handleLine();
} else {
if (mNextHandler != null) {
return mNextHandler.handle(lineType);
}
}
return "處理不了該英雄的對象";
}
@Override
public final void setNextHandler(IHandle handler) {
mNextHandler = handler;
}
public abstract String handleLine();
}
最后就是實(shí)現(xiàn)咱們所有對線狀況的handler對象
public class ADCHandler extends BaseHandler {
@Override
public String handleLine() {
return "作為射手英雄屏箍,請您走下路~";
}
@Override
public boolean canHandle(LineType lineType) {
return lineType == LineType.ADC;
}
}
public class AssistHandler extends BaseHandler {
@Override
public String handleLine() {
return "作為輔助英雄绘梦,請您走下路~";
}
@Override
public boolean canHandle(LineType lineType) {
return lineType == LineType.ASSIST;
}
}
public class DaddyHandler extends BaseHandler {
@Override
public String handleLine() {
return "作為打野英雄,請您走野區(qū)赴魁,在合適的時(shí)機(jī)游走三路~";
}
@Override
public boolean canHandle(LineType lineType) {
return lineType == LineType.DADDY;
}
}
public class MiddleHandler extends BaseHandler {
@Override
public String handleLine() {
return "作為中單英雄卸奉,請您走中路~";
}
@Override
public boolean canHandle(LineType lineType) {
return lineType == LineType.MIDDLE;
}
}
public class TopHandler extends BaseHandler {
@Override
public String handleLine() {
return "作為上單英雄,請您走上路~";
}
@Override
public boolean canHandle(LineType lineType) {
return lineType == LineType.TOP;
}
}
對外進(jìn)行一個(gè)封裝颖御,用以解耦择卦,注意,上文提到的對責(zé)任鏈的約束可以放到這里來寫約束策略,作為行為型的設(shè)計(jì)模式秉继,可以考慮復(fù)雜場景下利用創(chuàng)建型的設(shè)計(jì)模式來實(shí)例化咱們的 “責(zé)任鏈們”
public class ChainMatchSystem {
private IHandle mHandler;
public ChainMatchSystem() {
mHandler = new TopHandler();
IHandle middleHandle = new MiddleHandler();
IHandle adcHandle = new ADCHandler();
IHandle assistHandle = new AssistHandler();
IHandle daddyHandle = new DaddyHandler();
mHandler.setNextHandler(middleHandle);
middleHandle.setNextHandler(adcHandle);
adcHandle.setNextHandler(assistHandle);
assistHandle.setNextHandler(daddyHandle);
}
public void startMatchGame(IHandle.LineType lineType) {
System.out.println(mHandler.handle(lineType));
}
}
最后則是測試main方法
public static void main(String[] args) {
ChainMatchSystem chainMatchSystem = new ChainMatchSystem();
for (int i = 0; i < 5; i++) {
IHandle.LineType lineType = IHandle.LineType.OTHER;
if (i == 0) {
lineType = IHandle.LineType.ASSIST;
} else if (i == 1) {
lineType = IHandle.LineType.ADC;
} else if (i == 2) {
lineType = IHandle.LineType.TOP;
} else if (i == 3) {
lineType = IHandle.LineType.MIDDLE;
} else if (i == 4) {
lineType = IHandle.LineType.DADDY;
}
chainMatchSystem.startMatchGame(lineType);
}
}
//作為輔助英雄祈噪,請您走下路~
//作為射手英雄,請您走下路~
//作為上單英雄尚辑,請您走上路~
//作為中單英雄辑鲤,請您走中路~
//作為打野英雄,請您走野區(qū)杠茬,在合適的時(shí)機(jī)游走三路~
//修改一下月褥,看看OTHER對線出現(xiàn)時(shí)會怎么辦,只需要循環(huán)6次即可
public static void main(String[] args) {
ChainMatchSystem chainMatchSystem = new ChainMatchSystem();
for (int i = 0; i < 6; i++) {
IHandle.LineType lineType = IHandle.LineType.OTHER;
if (i == 0) {
lineType = IHandle.LineType.ASSIST;
} else if (i == 1) {
lineType = IHandle.LineType.ADC;
} else if (i == 2) {
lineType = IHandle.LineType.TOP;
} else if (i == 3) {
lineType = IHandle.LineType.MIDDLE;
} else if (i == 4) {
lineType = IHandle.LineType.DADDY;
}
chainMatchSystem.startMatchGame(lineType);
}
}
//作為輔助英雄瓢喉,請您走下路~
//作為射手英雄宁赤,請您走下路~
//作為上單英雄,請您走上路~
//作為中單英雄栓票,請您走中路~
//作為打野英雄决左,請您走野區(qū),在合適的時(shí)機(jī)游走三路~
//處理不了該英雄的對象
實(shí)際場景使用
在咱們Android開發(fā)中走贪,責(zé)任鏈的應(yīng)用有一個(gè)非常出名的庫佛猛,就是咱們的okhttp,感興趣的同學(xué)可以對照著咱們的責(zé)任鏈看一下~