天天看點

設計模式速記-職責鍊模式

模式定義

職責鍊模式又稱責任鍊模式,定義如下:

為了避免請求發送者與多個請求處理者耦合在一起,将所有請求的處理者通過前一對象記住其下一個對象的引用而連成一條鍊;當有請求發生時,可将請求沿着這條鍊傳遞,直到有對象處理它為止。

職責鍊模式的例子:

  • Struct 攔截器
  • JSP、Servlet的Filter
  • Javascript中的事件冒泡

優缺點

優點:

  • 降低了對象之間的耦合度。該模式使得一個對象無須知道到底是哪一個對象處理其請求以及鍊的結構,發送者和接收者也無須擁有對方的明确資訊。
  • 增強了系統的可擴充性。可以根據需要增加新的請求處理類,滿足開閉原則。
  • 增強了給對象指派職責的靈活性。當工作流程發生變化,可以動态地改變鍊内的成員或者調動它們的次序,也可動态地新增或者删除責任。
  • 責任鍊簡化了對象之間的連接配接。每個對象隻需保持一個指向其後繼者的引用,不需保持其他所有處理者的引用,這避免了使用衆多的 if 或者 if···else 語句。
  • 責任分擔。每個類隻需要處理自己該處理的工作,不該處理的傳遞給下一個對象完成,明确各類的責任範圍,符合類的單一職責原則。

缺點:

  • 不能保證每個請求一定被處理。由于一個請求沒有明确的接收者,是以不能保證它一定會被處理,該請求可能一直傳到鍊的末端都得不到處理。
  • 對比較長的職責鍊,請求的處理可能涉及多個處理對象,系統性能将受到一定影響。
  • 職責鍊建立的合理性要靠用戶端來保證,增加了用戶端的複雜性,可能會由于職責鍊的錯誤設定而導緻系統出錯,如可能會造成循環調用。

應用場景

  • 一個請求的處理需要多個步驟,但是具體是哪個步驟需要運作時才能确定
  • 計算機網絡中的令牌環網
  • Web應用很多,比如請求資料需要Filter,請求資料需要Format等

案例

案例描述

假如某員工要請假n天,上司角色有CEO、直屬上司(DirectLeader)和部門上司(DepartmentLeader),直屬上司可以批三天以内的假期,部門上司可以批一周以内的假期,更多時間隻有CEO有權批,使用職責鍊模式完成此案例。

示例代碼

上司抽象接口
/**
 * @Description 上司抽象接口
 */
public interface Leader {
    /**
     * 員工請假接口
     * 
     * @param days 請假天數
     * @return 是否有權準假
     */
    boolean accept(int days);

    /**
     * 擷取上司角色
     * @return 角色
     */
    String getCharacter();
}
           
上司具體角色
/**
 * @Description 上司具體角色 CEO
 */
public class CEO implements Leader {
    @Override
    public boolean accept(int days) {
        return true;
    }

    @Override
    public String getCharacter() {
        return "CEO";
    }
}
/**
 * @Description 上司具體角色 部門上司
 */
public class DepartmentLeader implements Leader {
    @Override
    public boolean accept(int days) {
        return days <= 7;
    }

    @Override
    public String getCharacter() {
        return "Department Leader";
    }
}
/**
 * @Description 上司具體角色 直屬上司
 */
public class DirectLeader implements Leader {
    @Override
    public boolean accept(int days) {
        return days <= 3;
    }

    @Override
    public String getCharacter() {
        return "Direct Leader";
    }
}
           
測試代碼
/**
 * @Description 職責鍊模式測試
 */
public class ChainOfResponsibilityTest {

    @Test
    public void test(){
        List<Leader> leaderChain = Lists.newArrayList();
        leaderChain.add(new DirectLeader());
        leaderChain.add(new DepartmentLeader());
        leaderChain.add(new CEO());

        int n = 4;
        for (Leader leader : leaderChain){
            if(leader.accept(n)){
                System.out.println(leader.getCharacter() + " accept");
                break;
            }
        }
    }
}
           
測試結果
Department Leader accept

Github 位址

https://github.com/duanqiangk/DesignPatternDemo.git