1. 程式人生 > >“戲”說設計模式——責任鏈模式

“戲”說設計模式——責任鏈模式

首先請出今天的主人公——“齊天大聖”孫悟空

原創文章,禁止轉載https://blog.csdn.net/wfy2695766757

 

小時候每到假期,電視上就會播出大家耳熟能詳的“西遊記” 。

那麼今天我們就通過“齊天大聖”孫悟空大鬧天宮來描述23種設計模式中之一的“責任鏈模式

首先我們先了解一下大鬧天宮的故事大概:西遊記中,孫悟空去東海龍宮搶了金箍棒,又去地府強銷生死簿。龍王、閻君去天庭告狀,玉帝把孫悟空召入天庭,授他做弼馬溫。悟空嫌官小,打回花果山,自稱“齊天大聖”。玉帝派托塔天王李靖率天兵天將捉拿孫悟空,沒有成功,便讓孫悟空管理蟠桃園。孫悟空偷吃蟠桃,毀了王母的蟠桃宴,又偷吃了

太上老君的金丹後逃離天宮。玉帝再派李天王率天兵捉拿;觀音菩薩舉薦二郎真君助戰;太上老君在旁使暗器幫助,最後悟空被擒。悟空被刀砍斧剁、火燒雷擊,甚至置丹爐鍛鍊四十九日,依然無事,還在天宮大打出手。玉帝降旨請來如來佛祖,才把孫悟空壓在五行山下。

在這個故事中有四個關鍵人物分別為:孫悟空托塔天王李靖玉帝如來佛祖

他們的關係圖為:

 

根據劇情發展,我們得到一個規律:孫悟空打敗了托塔天王李靖,打敗了玉帝,缺敗在瞭如來佛祖的手中。從中得知如來佛祖是最厲害的,沒有人能打敗他。

根據以上人物關係,我們來通過java描述他們的基本資訊:

public class LiJIng {//“托塔天王”李靖

    private String name;

    public LiJIng(String name) {
        this.name = name;
    }

    public boolean fighting(String SunWuKong){
        if ( ! SunWuKong.equals("孫悟空")){//判斷是否是與孫悟空打鬥
            System.out.println( name + "打敗挑戰者,挑戰者被李靖治罪!");
            //若不是孫悟空,則李靖打敗挑戰者
            return true;
        }else{
            System.out.println("孫悟空打敗" + name + "繼續前進,衝向天宮");
            //若是孫悟空,孫悟空打敗李靖,繼續前進
            return false;
        }
    }
}
public class YuHuangDaDi {//玉皇大帝

    private String name;

    public YuHuangDaDi(String name) {
        this.name = name;
    }

    public boolean fighting(String SunWuKong){
        if ( ! SunWuKong.equals("孫悟空")){
            System.out.println( name + "打敗挑戰者,挑戰者被玉帝治罪!");
            //若不是孫悟空,則玉帝打敗挑戰者
            return true;
        }else{
            System.out.println("孫悟空打敗" + name + "佔領天宮,獲得“齊天大聖”稱號");
            //若是孫悟空,孫悟空打敗玉帝,佔領天宮
            return false;
        }
    }
}
public class RuLaiFoZu {//如來佛祖

    private String name;

    public RuLaiFoZu(String name) {
        this.name = name;
    }

    public boolean fighting(String SunWuKong) {
        if (!SunWuKong.equals("孫悟空")) {
            System.out.println( name + "打敗挑戰者,挑戰者被如來佛祖治罪!");
            //若不是孫悟空,則如來佛祖打敗挑戰者
            return true;
        }else{
            System.out.println("孫悟空被" + name + "打敗,孫悟空被壓在五指山下,大鬧天宮結束!");
            //若是孫悟空,孫悟空被佛祖壓在五指山下
            return false;
        }
    }
}

接下來,我們設定一個場景“天宮”,所有人都在這個場景裡展開故事情節

/**
 * @Author by 飛宇
 * @Date 2018/12/19  20:16
 */
public class TianGong {//天宮作為場景
    public static void main(String[] args) {
        String SunWuKong = "孫悟空";//孫悟空出場
        LiJIng liJIng = new LiJIng("李靖");
        if ( ! liJIng.fighting(SunWuKong)){
            YuHuangDaDi yuHuangDaDi = new YuHuangDaDi("玉帝");
            if ( ! yuHuangDaDi.fighting(SunWuKong)){
                RuLaiFoZu ruLaiFoZu = new RuLaiFoZu("如來佛祖");
                ruLaiFoZu.fighting(SunWuKong);
            }
        }
    }
}

我們看看故事的發展情況:

功夫不負有心人,跑了三個地方和三個人打鬥,孫悟空終於完成了大鬧天宮的故事。

然而,我們的故事情節是不是有點過於複雜了,找這個打找那個打,打來打去好像孫悟空有點不耐煩了。

他說:“俺老孫打半天打累了,你們為什麼這麼麻煩,就不能一次都打完了嘛!?”

於是我們根據責任鏈模式來改進故事的發展情節:

進一步分析,挑戰的神仙肯定是不同的,並且每個神仙的戰鬥力會有區別,所以我們得把這些神仙的打鬥情節分開來寫,對每個神仙的打鬥情節我們進行定義,讓打鬥的神仙只知道自己是否能打過孫悟空(責任),如果打不過就讓更厲害的神仙去打(鏈條),開始重新定義情節,先抽象出一個神仙的類。

這回我的孫大聖分為三個等級分別為:初級孫悟空,中級孫悟空,高階孫悟空。初級只能打敗李靖,中級可以打敗李靖和玉帝,高階被如來佛祖打敗。

public abstract class ShenXian {//神仙的抽象類
    protected String name;// 抽象出神仙的姓名
    protected ShenXian bigShenXian;//更強大的神仙

    public ShenXian(String name) {
        this.name = name;
    }

    protected ShenXian setBigShenXian(ShenXian bigShenXian){
        this.bigShenXian = bigShenXian;
        return this.bigShenXian; //返回更強大的神仙,鏈式責任制度
    }

    public abstract void fighting(String SunWuKong);//抽象劇情發展由打鬥場景實現。
}

在第3行,神仙認識比自己更厲害的神仙,所以他可以請更厲害的神仙 ,持有強大神仙的引用。

在第9行,將強大神仙注入進來。

在第14行,是我們的情節推動,孫悟空將在這個場景中打鬥。

public class LiJIng extends ShenXian{

    public LiJIng(String name) {
        super(name);
    }//“托塔天王”李靖
    @Override
    public void fighting(String SunWuKong){
        if (  SunWuKong.equals("初級孫悟空")){//判斷是否是與孫悟空打鬥
            System.out.println( name + "打敗初級孫悟空,初級孫悟空被李靖治罪!");
            //若不是孫悟空,則李靖打敗挑戰者
        }else{
            System.out.println("孫悟空打敗" + name + "繼續前進,衝向天宮");
            //若是孫悟空,孫悟空打敗李靖,繼續前進
            this.bigShenXian.fighting(SunWuKong);
        }
    }
}

在第14行,表明自己打不過孫悟空,請強大神仙代替自己打鬥。 

public class YuHuangDaDi extends ShenXian{

    public YuHuangDaDi(String name) {
        super(name);
    }//玉皇大帝
    @Override
    public void fighting(String SunWuKong){
        if (SunWuKong.equals("中級孫悟空")){
            System.out.println( name + "打敗挑戰者,挑戰者被玉帝治罪!");
            //若不是孫悟空,則玉帝打敗挑戰者
        }else{
            System.out.println("孫悟空打敗" + name + "佔領天宮,獲得“齊天大聖”稱號");
            //若是孫悟空,孫悟空打敗玉帝,佔領天宮
            this.bigShenXian.fighting(SunWuKong);
        }
    }
}
public class RuLaiFoZu extends ShenXian{

    public RuLaiFoZu(String name) {
        super(name);
    }//如來佛祖
    @Override
    public void fighting(String SunWuKong) {
        if (SunWuKong.equals("高階孫悟空")) {
            System.out.println( name + "打敗挑戰者,挑戰者被如來佛祖治罪!");
            //若不是孫悟空,則如來佛祖打敗挑戰者
        }else{
            System.out.println("孫悟空被" + name + "打敗,孫悟空被壓在五指山下,大鬧天宮結束!");
            //若是孫悟空,孫悟空被佛祖壓在五指山下
            this.bigShenXian.fighting(SunWuKong);
        }
    }
}
/**
 * @Author by 飛宇
 * @Date 2018/12/19  20:16
 */
public class TianGong {//天宮作為場景
    public static void main(String[] args) {

        ShenXian shenXian = new LiJIng("李靖");
        shenXian.setBigShenXian(new YuHuangDaDi("玉帝"))
                .setBigShenXian(new RuLaiFoZu("如來佛祖"));
        shenXian.fighting("初級孫悟空");
        /**
         * 李靖打敗初級孫悟空,初級孫悟空被李靖治罪!
         */
        shenXian.fighting("中級孫悟空");
        /**
         * 孫悟空打敗李靖繼續前進,衝向天宮
         * 玉帝打敗挑戰者,挑戰者被玉帝治罪!v
         */
        shenXian.fighting("高階孫悟空");
        /**
         * 孫悟空打敗李靖繼續前進,衝向天宮
         * 孫悟空打敗玉帝佔領天宮,獲得“齊天大聖”稱號
         * 如來佛祖打敗挑戰者,挑戰者被如來佛祖治罪!
         */
    }
}

在上述程式碼中對責任鏈構造物件,(鏈式)傳遞(責任)。

這樣孫悟空就可以一次性完成打鬥,我們看到初級孫悟空只能打過李靖,而高階孫悟空才可以被如來佛祖打敗。

目的

孫悟空和重神仙實現了解耦,這樣孫悟空只需要給這條責任鏈傳遞自己的等級,便可完成自己的情節。不用操心自己是否要找到下一個神仙在開始打鬥,只需要交給神仙的介面即可。每個神仙(角色)的責任被劃分的非常清楚,然後將這些責任通過(鏈式)穿起來,形成了完整的責任範圍鏈。如果想讓孫悟空打敗更多的神仙,只需要按規範新增一個神仙(角色)到責任鏈中即可,這樣一個可伸縮的責任鏈就完成了,它擁有完美的可擴充套件性

加個關注吧,下次接著看!謝謝!!!

謝謝https://blog.csdn.net/wfy2695766757