責任鏈模式

中國古代對婦女制定了“三從四德”的道德規範,“三從”是指“未嫁從父、既嫁從夫、夫
死從子”。也就是說,一位女性在結婚之前要聽從於父親,結婚之後要聽從於丈夫,如果丈
夫死了還要聽從於兒子。舉例來說,如果一位女性要出去逛街,在她出嫁前必須徵得父親的
同意,出嫁之後必須獲得丈夫的許可,那丈夫死了怎麼辦?那就得問問兒子是否允許自己出
去逛街。估計你接下來馬上要問:“要是沒有兒子怎麼辦?”那就請示小叔子、侄子等。在父
系社會中,婦女只佔從屬地位,現在想想中國古代的婦女還是挺悲慘的,連逛街都要多番請
示。作爲父親、丈夫或兒子,只有兩種選擇:要不承擔起責任來,允許她或不允許她逛街;
要不就讓她請示下一個人,這是整個社會體系的約束,應用到我們項目中就是業務規則。下
面來看如何通過程序來實現“三從”,需求很簡單:通過程序描述一下古代婦女的“三從”制
度。好,我們先來看類圖,如圖

類圖非常簡單,IHandler是三個有決策權對象的接口,IWomen是女性的代碼,其實現也
非常簡單

package ZeRenLianP;

public interface IWomen {
    /**
     * 一個是取得當前的個人狀況getType,通過返回值決定是結婚了還
     是沒結婚、丈夫是否在世等
     * @return
     */
    public int getType();

    /**
     * 方法getRequest是要請示的內容,要出去逛街還是吃
     飯
     * @return
     */
    public String getRequest();
}
package ZeRenLianP;

public class Women implements IWomen {
    /**
     * 通過一個int類型的參數來描述婦女的個人狀況
     * 1--未出嫁
     * 2--出嫁
     * 3--夫死
     * @return
     */
    private int type = 0;
    private String request = "";

    public Women(int type,String request){
        this.type = type;
        this.request = request;
    }
    @Override
    public int getType() {
        return this.type;
    }

    @Override
    public String getRequest() {
        return this.request;
    }
}
package ZeRenLianP;

public interface IHandler {
    public void HandleMessage(Women women);
}
package ZeRenLianP;

public class Father implements IHandler {
    @Override
    public void HandleMessage(Women women) {
        System.out.println("女兒的請示是:"+women.getRequest());
        System.out.println("父親的答覆是:同意");
    }
}
package ZeRenLianP;

public class Husband implements IHandler {
    @Override
    public void HandleMessage(Women women) {
        System.out.println("妻子的請示是:"+women.getRequest());
        System.out.println("丈夫的答覆是:同意");
    }
}
package ZeRenLianP;

public class Son implements IHandler {
    @Override
    public void HandleMessage(Women women) {
        System.out.println("母親的請示是:"+women.getRequest());
        System.out.println("兒子的答覆是:同意");
    }
}
package ZeRenLianP;

import java.util.ArrayList;
import java.util.Random;

public class Client {
    public static void main(String[] args) {
        Random random = new Random();
        ArrayList<Women> womenArrayList =new ArrayList<>();
        for (int i = 0; i<5 ; i++){
            womenArrayList.add(new Women(random.nextInt(4),"guangjie"));
        }
        IHandler father = new Father();
        IHandler husband = new Husband();
        IHandler son = new Son();
        for (Women women:womenArrayList){
            if(women.getType() ==1){ //未結婚少女,請示父親
                System.out.println("\n--------女兒向父親請示-------");
                father.HandleMessage(women);
            }else if(women.getType() ==2){ //已婚少婦,請示丈夫
                System.out.println("\n--------妻子向丈夫請示-------");
                husband.HandleMessage(women);
            }else if(women.getType() == 3){ //母親請示兒子
                System.out.println("\n--------母親向兒子請示-------");
                son.HandleMessage(women);
            }else{
//暫時什麼也不做
            }
        }
    }
}

代碼有以下幾個問題:
● 職責界定不清晰
對女兒提出的請示,應該在父親類中做出決定,父親有責任、有義務處理女兒的請示,
因此Father類應該是知道女兒的請求自己處理,而不是在Client類中進行組裝出來,也就是說
原本應該是父親這個類做的事情拋給了其他類進行處理,不應該是這樣的。
● 代碼臃腫
我們在Client類中寫了if...else的判斷條件,而且能隨着能處理該類型的請示人員越
多,if...else的判斷就越多,想想看,臃腫的條件判斷還怎麼有可讀性?!
● 耦合過重
這是什麼意思呢,我們要根據Women的type來決定使用IHandler的那個實現類來處理請
求。有一個問題是:如果IHandler的實現類繼續擴展怎麼辦?修改Client類?與開閉原則違背
了!
● 異常情況欠考慮
妻子只能向丈夫請示嗎?如果妻子(比如一個現代女性穿越到古代了,不懂什麼“三從
四德”)向自己的父親請示了,父親應該做何處理?我們的程序上可沒有體現出來,邏輯失
敗了!

可以抽象成這樣一個結構,女性的請求先發送到父親類,父親類一看是自己要處理的,就
作出迴應處理,如果女兒已經出嫁了,那就要把這個請求轉發到女婿來處理,那女婿一旦去
天國報道了,那就由兒子來處理這個請求。

package ZeRenLianP;

public abstract class Handle {
    public final static int FATHER_LEVEL_REQUEST = 1;
    public final static int HUSBAND_LEVEL_REQUEST = 2;
    public final static int SON_LEVEL_REQUEST = 3;
    //能處理的級別
    private int level =0;
    //責任傳遞,下一個人責任人是誰
    private Handle nextHandler;
    //每個類都要說明一下自己能處理哪些請求
    public Handle(int _level){
        this.level = _level;
    }

//一個女性(女兒、妻子或者是母親)要求逛街,你要處理這個請求
    public final void HandleMessage(Women women){
        if (women.getType() == this.level){
            this.response(women);
        }else {
            if (this.nextHandler != null){
                this.nextHandler.HandleMessage(women);
            }else {
                System.out.println("沒有人了,不同意");
            }
        }
    }

    /**
     * 如果不屬於你處理的請求,你應該讓她找下一個環節的人,如女兒出嫁了,
     * 還向父親請示是否可以逛街,那父親就應該告訴女兒,應該找丈夫請示
     * @param
     */
    public void setNext(Handle handle){
        this.nextHandler = handle;
    }
    protected abstract void response(IWomen w);
}
package ZeRenLianP;

public class Father extends Handle {
    public Father(){
        super(Handle.FATHER_LEVEL_REQUEST);
    }
    @Override
    protected void response(IWomen women) {
        System.out.println("--------女兒向父親請示-------");
        System.out.println(women.getRequest());
        System.out.println("父親的答覆是:同意\n");
    }
}
package ZeRenLianP;

public class Husband extends Handle {
    public Husband(){
        super(Handle.HUSBAND_LEVEL_REQUEST);
    }
    @Override
    protected void response(IWomen women) {
        System.out.println("--------妻子向丈夫請示-------");
        System.out.println(women.getRequest());
        System.out.println("丈夫的答覆是:同意\n");
    }
}
package ZeRenLianP;

public class Son extends Handle {
    public Son(){
        super(Handle.SON_LEVEL_REQUEST);
    }
    @Override
    protected void response(IWomen women) {
        System.out.println("--------母親向兒子請示-------");
        System.out.println(women.getRequest());
        System.out.println("兒子的答覆是:同意\n");
    }
}
package ZeRenLianP;

public class Women implements IWomen {
    /**
     * 通過一個int類型的參數來描述婦女的個人狀況
     * 1--未出嫁
     * 2--出嫁
     * 3--夫死
     * @return
     */
    private int type = 0;
    private String request = "";

    public Women(int type,String request){
        this.type = type;
        //this.request = request;
        switch (type){
            case 1:
                this.request = "女兒的請求是:" + request;
                break;
            case 2:
                this.request = "妻子的請求是:" + request;
                break;
            case 3:
                this.request = "母親的請求是:" + request;
        }

    }
    @Override
    public int getType() {
        return this.type;
    }

    @Override
    public String getRequest() {
        return this.request;
    }
}
package ZeRenLianP;

import java.util.ArrayList;
import java.util.Random;

public class Client1 {
    public static void main(String[] args) {
        //隨機挑選幾個女性
        Random rand = new Random();
        ArrayList<Women> arrayList = new ArrayList();
        for(int i=0;i<5;i++){
            arrayList.add(new Women(rand.nextInt(4),"我要出去逛街"));
        }
//定義三個請示對象
        Handle father = new Father();
        Handle husband = new Husband();
        Handle son = new Son();
//設置請示順序
        father.setNext(husband);
        husband.setNext(son);
        for (Women women:arrayList){
            father.HandleMessage(women);
        }
    }
}

責任鏈模式定義如下:
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.(使多個對象都有機會處理請求,從而避免了請求的發送者和接受者之間的耦合關
系。將這些對象連成一條鏈,並沿着這條鏈傳遞該請求,直到有對象處理它爲止。)

抽象的處理者實現三個職責:一是定義一個請求的處理方法handleMessage,唯一對外開
放的方法;二是定義一個鏈的編排方法setNext,設置下一個處理者;三是定義了具體的請求
者必須實現的兩個方法:定義自己能夠處理的級別getHandlerLevel和具體的處理任務echo。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章