java/android設計模式-行為模式之責任鏈模式

故名思義責任鏈模式中存在一個鏈式結構,鏈式結構:多外節點首尾相連,每個節點都可以被拆分再連接。具體什么是責任鏈模式呢。它使多個對象都有機會處理請求,從而避免請求的發送者和接受者之間的耦合關系,將這個對象連成一條鏈,并沿著這個條鏈傳遞該請求,直到有一個對象處理它為止。將每一個節點看作是一個對象,每一個對象擁有不同的處理邏輯,將一個請求從鏈式的首段發出,沿著鏈的路徑傳遞給每一個節點對象,直到有對象處理這個請求為止。
責任鏈模式看起來可能比較陌生,可是我們在日常開發卻經常碰到這種形式。

 public void handleSomething(int eventNum){
        switch (eventNum){
            case 1:
//do something
                break;
            case 2:
//do something
                break;
            case 3:
//do something
                break;
                default:
//do something
        }
    }

switch或者if-else這種就是責任鏈的裸體樣式,是最簡單的實現格式。當然這是個不恰當的例子,if-else嵌套太多,很可能你都看不懂你的代碼。

舉個粟子

下面給一個簡單的例子:
這個例子很簡單,一個抽象的Handler(處理者角色)和一個繼承Handler的具體實現者ConcreteHandler。

類圖

類圖

代碼

Handler類:

public abstract class Handler {
    /**
     * 持有下一個處理節點
     */
    protected Handler successor;

    /**
     * 這個方法是具體的請求處理方法,在這里為了簡化而沒有傳入參數
     */
    public abstract void handleRequest();

    /**
     * 取出下一個節點的方法
     */
    public Handler getSuccessor() {
        return successor;
    }

    /**
     * 賦值下一個節點的方法
     */
    public void setSuccessor(Handler successor) {
        this.successor = successor;
    }
}

ConcreteHandler 類:

public class ConcreteHandler extends Handler {
    @Override
    public void handleRequest() {
        /**
         * 判斷是否有下個節點的責任處理對象
         * 如果有,就轉發請求給下一個責任處理對象
         * 如果沒有,則處理請求
         */
        if (getSuccessor() != null) {
            System.out.println("放過請求");
            getSuccessor().handleRequest();
        } else {
            System.out.println("處理請求");
        }
    }
}

Cilent類:

public class Client {
    public static void main(String[] args) {
        Handler handler1 = new ConcreteHandler();
        Handler handler2 = new ConcreteHandler();
        handler1.setSuccessor(handler2);
        handler1.handleRequest();
    }
}

Android/java 中應用責任鏈模式的場景

  • 在android比較明顯的就是事件分發過程中對事件的投遞。嚴格說來,事件投遞并不是嚴格的責任鏈模式,是責任鏈模式的變種實現。子 View 的 onTouchEvent 返回 true 代碼消費該事件并不再傳遞,false 代表不消費并且傳遞到父 ViewGroup 去處理,這些樹形結構的子 View 就是責任鏈上一個個處理對象;
  • OrderedBroadcast,廣播的每一個接收者按照優先級依次接受消息,如果處理完成之后可以調用 abortBroadcast 終止廣播,不是自己處理的就可以傳遞給下一個處理者;
  • try-catch語句,每一個 catch 根據 Exception 類型進行匹配,形成一個責任鏈,如果有一個 catch 語句與該 Exception 符合,這個 Exception 就交由給它進行處理,之后所有 catch 語句都不會再次執行。

再來看看具體的粟子

如果一個程序員一個月連續加班,這個月算下來可以調休5天。然后這個coder寫了調休申請給項目經理,可項目經理有點方了,他只能審批調休一天的,然后項目經理把你的申請交給部門經理,部門經理一看也沒法,公司規則多,他只能審批多超過三天的,只能讓總經理過目了。
那看看具體代碼。

//這個是leader的抽象類
public abstract class Leader {
    private Leader successor;
    private int hoildayNum;
    private String position;

    public void setPosition(String position) {
        this.position = position;
    }

    public String getPosition() {
        return position;
    }

    public Leader(int hoildayNum) {
        this.hoildayNum = hoildayNum;
    }

    public abstract void reply(Worker worker);

    public void handleRequest(Worker worker) {
        if (worker.getHolidayNum() <= hoildayNum) {
            reply(worker);
        } else {
            if (null != successor) {
                successor.handleRequest(worker);
            } else {
                System.out.println(position + "拒絕了你的請求");
            }
        }
    }

    public void setSuccessor(Leader successor) {
        this.successor = successor;
    }
}
/**
 * 項目經理處理類
 */
public class ProjectDirector extends Leader {

    public ProjectDirector(int hoildayNum) {
        super(hoildayNum);
        setPosition("項目經理");
    }

    @Override
    public void reply(Worker worker) {
        System.out.println(getPosition() + "已通過你的請求");
    }
}
/**
 * 部門經理處理類
 */
public class DepartmentManager extends Leader {
 public DepartmentManager(int hoildayNum) {
        super(hoildayNum);
        setPosition("部門經理");
    }

    @Override
    public void reply(Worker worker) {
        System.out.println(getPosition() + "已通過你的請求");
    }}
/**
 * 總經理處理類
 */
public class GeneralManager extends Leader {

    public GeneralManager(int hoildayNum) {
        super(hoildayNum);
        setPosition("總經理");
    }

    @Override
    public void reply(Worker worker) {
        System.out.println(getPosition() + "已通過請求");
    }
}
public class Cilent {
    public static void main(String[] args) {
        Worker worker = new Worker(6);

        Leader projectDir = new ProjectDirector(1);
        Leader departmentMan = new DepartmentManager(3);
        Leader generalMan = new GeneralManager(10);
        projectDir.setSuccessor(departmentMan);
        departmentMan.setSuccessor(generalMan);

        projectDir.handleRequest(worker);
    }
}

這樣我們就把請求者與處理者優雅的解耦。

純與不純的責任鏈模式

很多資料中會介紹純和不純的責任鏈模式,在標準的責任鏈模式中,責任鏈上的一個節點只允許有兩個行為:處理或者推給下個節點處理,而不允許處理完之后又推給下個節點,前者被很多資料稱為純的責任鏈模式,而后者被稱為不純的責任鏈模式。其實在實際的系統里,純的責任鏈很難找到。如果堅持責任鏈不純便不是責任鏈模式,那么責任鏈模式便不會有太大意義了。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,362評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,577評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 178,486評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,852評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,600評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,944評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,944評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,108評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,652評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,385評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,616評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,111評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,798評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,205評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,537評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,334評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,570評論 2 379

推薦閱讀更多精彩內容

  • 1 場景問題# 1.1 申請聚餐費用## 來考慮這樣一個功能:申請聚餐費用的管理。 很多公司都有這樣的福利,就是項...
    七寸知架構閱讀 3,167評論 3 58
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,828評論 18 139
  • 工廠模式類似于現實生活中的工廠可以產生大量相似的商品,去做同樣的事情,實現同樣的效果;這時候需要使用工廠模式。簡單...
    舟漁行舟閱讀 7,805評論 2 17
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,737評論 18 399
  • #幸福是需要修出來的~每天進步1%~幸福實修08班~8唐潔-富陽# 20170903(77/99) 【幸福三朵玫瑰...
    你謝謝閱讀 176評論 1 4