Android源碼設計模式學習筆記-責任鏈模式

當處理一個事件是根據(jù)這個事件的某個條件去決定哪個處理對象的時候可以考慮使用責任鏈模式.


image.png

具體我們從一個代碼示范入手千埃,定義一個抽象的處理者

public abstract class AbstractHandler {
    public AbstractHandler nextHandler;

    /**
     * 處理請求,當Request Level 和 Handle Level相等就表明該請求交由該處理者處理
     */
    public final void handleRequest(AbstractRequest request){
        if (getHandleLevel() == request.getRequestLevel()){
            handle(request);
        }else {
            if (nextHandler != null){
                nextHandler.handle(request);
            } else{
                System.out.println("All of handler can not handle the request");
            }
        }
    }

    /**
     * 獲取處理對象的處理級別
     * @return
     */
    protected abstract int getHandleLevel();

    /**
     * 每個處理對象的具體處理方式
     */
    protected abstract void handle(AbstractRequest request);

}

再定義一個抽象的請求

public abstract class AbstractRequest {
    private Object obj;

    public AbstractRequest(Object obj) {
        this.obj = obj;
    }

    /**
     * 獲取處理內(nèi)容的對象
     */
    public Object getContent(){
        return obj;
    }

    /**
     * 獲取請求級別
     */
    public abstract int getRequestLevel();
}

下面分別定義3個實際的處理者和3個實際的請求

public class Handler1 extends AbstractHandler{
    @Override
    protected int getHandleLevel() {
        return 1;
    }

    @Override
    protected void handle(AbstractRequest request) {
        System.out.println("Handler1 handle request : "+request.getRequestLevel());
    }
}
public class Handler2 extends AbstractHandler{
    @Override
    protected int getHandleLevel() {
        return 2;
    }

    @Override
    protected void handle(AbstractRequest request) {
        System.out.println("Handler2 handle request : "+request.getRequestLevel());
    }
}
public class Handler3 extends AbstractHandler{
    @Override
    protected int getHandleLevel() {
        return 3;
    }

    @Override
    protected void handle(AbstractRequest request) {
        System.out.println("Handler3 handle request : "+request.getRequestLevel());
    }
}
public class Request1 extends AbstractRequest{
    public Request1(Object obj) {
        super(obj);
    }

    @Override
    public int getRequestLevel() {
        return 1;
    }
}
public class Request2 extends AbstractRequest{
    public Request2(Object obj) {
        super(obj);
    }

    @Override
    public int getRequestLevel() {
        return 2;
    }
}
public class Request3 extends AbstractRequest{
    public Request3(Object obj) {
        super(obj);
    }

    @Override
    public int getRequestLevel() {
        return 3;
    }
}

最終調(diào)用

Handler1 handler1 = new Handler1();
Handler2 handler2 = new Handler2();
Handler3 handler3 = new Handler3();
/**
* 構建責任鏈
*/
handler1.nextHandler = handler2;
handler2.nextHandler = handler3;

Request1 request1 = new Request1("request 1");
Request2 request2 = new Request2("request 2");
Request3 request3 = new Request3("request 3");

handler1.handleRequest(request1);
handler1.handleRequest(request2);
handler3.handleRequest(request3);

輸出:

01-13 21:33:44.684 22261-22261/? I/System.out: Handler1 handle request : 1
01-13 21:33:44.684 22261-22261/? I/System.out: Handler2 handle request : 2
01-13 21:33:44.684 22261-22261/? I/System.out: Handler3 handle request : 3

上面我們創(chuàng)建Request并交給Handler構建的一條責任鏈處理捂人,當滿足Request的Level和Handler的Level相等的情況就交由該Handler進行處理幼东,這就是一個責任鏈的基本實現(xiàn).
下面在再舉一個實際栗子看看運用上面這套責任鏈模式代碼.
目前小明出國出差回來拨与,出差的經(jīng)費是50000元瓦胎,小明需要報銷這筆經(jīng)費猿规,他首先找到他的組長處理報銷問題衷快,但是組長這邊只能處理1000元以下的報銷,組長表示找上面的部門主管批復姨俩,于是找到部門主管蘸拔,部門主管只能處理5000以下的報銷,于是部門主管找到經(jīng)理批復环葵,經(jīng)理只能處理10000元以下的報銷调窍,于是經(jīng)理找到老板,進行報銷批復张遭。處理報銷經(jīng)費事件這一連串人可以看作是一個責任鏈邓萨,我們可以用責任鏈模式去實現(xiàn)上面的需求.
先抽象領導

public abstract class Leader {
    //上級領導
    public Leader nextHandler;

    public final void handleRequest(int money){
        /**
         * 如果報銷經(jīng)費小于該領導的處理范圍,則處理.
         */
        if (money < limit()){
            handle(money);
        } else {
            /**
             * 不滿足交給上級領導進行處理
             */
            if (null != nextHandler){
                nextHandler.handleRequest(money);
            }
        }
    }

    /**
     * 處理經(jīng)費上限
     * @return
     */
    public abstract int limit();

    /**
     * 處理報銷
     * @param money
     */
    protected abstract void handle(int money);
}

具體的四個領導

public class GroupLeader extends Leader{
    @Override
    public int limit() {
        return 1000;
    }

    @Override
    protected void handle(int money) {
        System.out.println("組長批復報銷 "+money+" 元");
    }
}
public class Director extends Leader{
    @Override
    public int limit() {
        return 5000;
    }

    @Override
    protected void handle(int money) {
        System.out.println("主管批復報銷 "+money+"元");
    }
}
public class Manager extends Leader{
    @Override
    public int limit() {
        return 10000;
    }

    @Override
    protected void handle(int money) {
        System.out.println("經(jīng)理批復報銷 "+money+"元");
    }
}
public class Boss extends Leader{
    @Override
    public int limit() {
        return Integer.MAX_VALUE;
    }

    @Override
    protected void handle(int money) {
        System.out.println("老板批復報銷"+money+"元");
    }
}

最后調(diào)用

GroupLeader groupLeader = new GroupLeader();
Director director = new Director();
Manager manager = new Manager();
Boss boss = new Boss();
groupLeader.nextHandler = director;
director.nextHandler = manager;
manager.nextHandler = boss;
groupLeader.handleRequest(50000);

輸出

01-13 21:48:40.181 22459-22459/? I/System.out: 老板批復報銷50000元

其實責任鏈模式也并不是一定要按照上面那套模版代碼去實現(xiàn)菊卷,關鍵是要突出處理一個事件的處理者再不滿足處理該事件條件的情況下把事件傳遞給下一個處理者這種思想. 最后再來一個栗子,在Android開發(fā)中廣播分為兩種先誉,一種是Normal Broadcast另外一種是Order Broadcast, 發(fā)送Normal Broadcast是所有注冊該廣播的廣播接收者都能接收到。Order Broadcast是按照廣播接收者優(yōu)先級依次發(fā)送的烁,接收到該廣播的廣播接收者可以選擇是否繼續(xù)向下傳遞褐耳,我們可以利用Order Broadcast這樣的機制來實現(xiàn)一條責任鏈.

public class FirstBroadcastReceiver extends BroadcastReceiver{
    @Override
    public void onReceive(Context context, Intent intent) {
        int limit = intent.getIntExtra("limit",-1001);
        if (limit == 1000){
            String msg = intent.getStringExtra("msg");
            Toast.makeText(context,msg,Toast.LENGTH_SHORT).show();
            abortBroadcast();
        } else {
            Bundle b = new Bundle();
            b.putString("new","Message from FirstReceiver");
            setResultExtras(b);
        }
    }
}
public class SecondBroadcastReceiver extends BroadcastReceiver{
    @Override
    public void onReceive(Context context, Intent intent) {
        int limit = intent.getIntExtra("limit",-1001);
        if (limit == 100){
            String msg = intent.getStringExtra("msg");
            //取上一個receiver的附加信息
            Bundle b = getResultExtras(true);
            String str = b.getString("new");

            Toast.makeText(context,msg+" ----- "+str,Toast.LENGTH_SHORT).show();

            abortBroadcast();
        }else{
            Bundle b = new Bundle();
            b.putString("new","Message from SecondReceiver");
            setResultExtras(b);
        }
    }
}
public class ThirdBroadcastReceiver extends BroadcastReceiver{
    @Override
    public void onReceive(Context context, Intent intent) {
        int limit = intent.getIntExtra("limit",-1001);

        if (limit == 10){
            String msg = intent.getStringExtra("msg");

            Bundle b = getResultExtras(true);
            String str = b.getString("new");

            Toast.makeText(context,msg+" ---- "+str,Toast.LENGTH_SHORT).show();

            abortBroadcast();
        }else{
            Bundle b = new Bundle();
            b.putString("new","Message from ThirdReceiver");
            setResultExtras(b);
        }
    }
}

在AndroidManifest.xml中申明這3個Receiver,并設置對應的權限值.

        <receiver android:name=".broadcast.FirstBroadcastReceiver">
            <intent-filter
                android:priority="1000"
                >
                <action android:name="com.example.huangli.action.ORDER_BROADCAST"></action>
            </intent-filter>
        </receiver>
        <receiver android:name=".broadcast.SecondBroadcastReceiver">
            <intent-filter
                android:priority="100"
                >
                <action android:name="com.example.huangli.action.ORDER_BROADCAST"></action>
            </intent-filter>
        </receiver>
        <receiver android:name=".broadcast.ThirdBroadcastReceiver">
            <intent-filter
                android:priority="10"
                >
                <action android:name="com.example.huangli.action.ORDER_BROADCAST"></action>
            </intent-filter>
        </receiver>

最后調(diào)用:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        sendBroadcast();
    }

    private void sendBroadcast() {
        Intent intent = new Intent();
        intent.setAction("com.example.huangli.action.ORDER_BROADCAST");
        intent.putExtra("limit", 100);
        intent.putExtra("msg", "Message from MainActivity");
        sendOrderedBroadcast(intent, null);
    }

}

我們將limit設置成了100,它會在SecondBroadcastReceiver進行處理渴庆,實際效果大家可以試試铃芦。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市襟雷,隨后出現(xiàn)的幾起案子刃滓,更是在濱河造成了極大的恐慌,老刑警劉巖耸弄,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件咧虎,死亡現(xiàn)場離奇詭異,居然都是意外死亡计呈,警方通過查閱死者的電腦和手機砰诵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來捌显,“玉大人茁彭,你說我怎么就攤上這事》鐾幔” “怎么了理肺?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我妹萨,道長年枕,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任乎完,我火速辦了婚禮熏兄,結果婚禮上,老公的妹妹穿的比我還像新娘囱怕。我一直安慰自己,他們只是感情好毫别,可當我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布娃弓。 她就那樣靜靜地躺著,像睡著了一般岛宦。 火紅的嫁衣襯著肌膚如雪台丛。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天砾肺,我揣著相機與錄音挽霉,去河邊找鬼。 笑死变汪,一個胖子當著我的面吹牛侠坎,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播裙盾,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼实胸,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了番官?” 一聲冷哼從身側響起庐完,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎徘熔,沒想到半個月后门躯,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡酷师,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年讶凉,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片山孔。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡缀遍,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出饱须,到底是詐尸還是另有隱情域醇,我是刑警寧澤,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站譬挚,受9級特大地震影響锅铅,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜减宣,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一盐须、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧漆腌,春花似錦贼邓、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至填具,卻和暖如春统舀,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背劳景。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工誉简, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人盟广。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓闷串,卻偏偏與公主長得像,于是被迫代替她去往敵國和親筋量。 傳聞我的和親對象是個殘疾皇子窿克,可洞房花燭夜當晚...
    茶點故事閱讀 44,843評論 2 354

推薦閱讀更多精彩內(nèi)容