設計模式-委派模式

設計模式-委託模式

模式定義

舒適提示:內容較多建議收藏閱讀,大約須要5分鐘。java

代碼可在GitHub中閱讀:歡迎star。github.com/UniqueDong/…git

在經常使用的23種設計模式中其實面沒有委派模式(delegate)的影子,可是在 Spring 中委派模式確實用的比較多的一種模式,Spring MVC 框架中的DispatcherServlet其實就用到了委派模式github

其實我我的的理解就是一個特殊的靜態代理模式,只不過加入了策略模式,咱們看下面的圖。算法

策略模式的環境上下文角色只有一個策略抽象的引用,而後根據條件設置對應的策略調用。而委託持有全部的策略,根據條件去將請求委託到對應的實現類中執行。設計模式

委派模式

策略模式

咱們經過一個簡單例子來看看策略模式:它只只有一個策略的引用,根據不一樣場景切換策略。bash

  • 環境(Context)角色:持有一個Strategy的引用。
  • 抽象策略(Strategy)角色:這是一個抽象角色,一般由一個接口或抽象類實現。
  • 具體策略(ConcreteStrategy)角色:包裝了相關的算法或行爲。

使用場景

假設如今要設計一個販賣各種書籍的電子商務網站的購物車系統。app

一個最簡單的狀況就是把全部貨品的單價乘上數量,可是實際狀況確定比這要複雜。框架

好比,本網站可能對全部的高級會員提供每本20%的促銷折扣;對中級會員提供每本10%的促銷折扣;對初級會員沒有折扣。ide

根據描述,折扣是根據如下的幾個算法中的一個進行的:函數

  • 算法一:對初級會員沒有折扣。
  • 算法二:對中級會員提供10%的促銷折扣。
  • 算法三:對高級會員提供20%的促銷折扣。

代碼實現以下:定義抽象策略角色

/** * 抽象折扣類(抽象策略(Strategy)角色) */
public interface MemberStrategy {

    /** * 計算圖書的價格 * @param booksPrice 原書價格 * @return 打折後的價格 */
    double calcPrice(double booksPrice);
}
複製代碼

而後定義咱們針對不一樣會員的折扣算法實現

/** * 具體策略(ConcreteStrategy)角色 * 初級會員折扣具體策略 */
public class PrimaryMemberStrategy implements MemberStrategy {

    @Override
    public double calcPrice(double booksPrice) {
        System.out.println("對初級會員沒有打折");
        return booksPrice;
    }
}

/** * 中級會員折扣策略 */
public class IntermediteMemberStrategy implements MemberStrategy {

    @Override
    public double calcPrice(double booksPrice) {
        System.out.println("對於中級會員的折扣爲10%");
        return booksPrice * 0.9;
    }
}


/** * 高級會員折扣策略 */
public class AdvanceMemberStrategy implements MemberStrategy {

    @Override
    public double calcPrice(double booksPrice) {
        return booksPrice * 0.8;
    }
}
複製代碼

最後咱們還需定義個策略上下文角色,它只有一個抽象策略的引用。

/** * 環境(Context)角色:持有一個Strategy的引用。 * Created by unique on 2017/6/1. */
public class PriceContext {
    /** * 持有一個具體的策略對象 */
    private MemberStrategy memberStrategy;

    /** * 構造方法,傳入一個具體策略 * @param memberStrategy */
    public PriceContext(MemberStrategy memberStrategy) {
        this.memberStrategy = memberStrategy;
    }

    /** * 計算圖書的價格 * @param booksPrice * @return */
    public double calcPrice(double booksPrice) {
        return memberStrategy.calcPrice(booksPrice);
    }

    public void setMemberStrategy(MemberStrategy memberStrategy) {
        this.memberStrategy = memberStrategy;
    }
}
複製代碼

最後咱們編寫客戶端來模擬

public class Clinet {
    public static void main(String[] args) {
        //選擇並建立所要的策略
        MemberStrategy strategy = new AdvanceMemberStrategy();

        //建立環境
        PriceContext context = new PriceContext(strategy);
        double booksPrice = 500.98;
        double price = context.calcPrice(booksPrice);
        System.out.println("圖書的原價:" + booksPrice + "打折後的最終價格:" + price);

        System.out.println("----切換會員----");
        strategy = new PrimaryMemberStrategy();
        context.setMemberStrategy(strategy);

        price = context.calcPrice(booksPrice);
        System.out.println("圖書的原價:" + booksPrice + "打折後的最終價格:" + price);
    }

}
複製代碼

打印結果以下所示:

書的原價:500.98打折後的最終價格:400.78400000000005
----切換會員----
對初級會員沒有打折
圖書的原價:500.98打折後的最終價格:500.98
複製代碼

委派模式

主要角色

  • DispatcherServlet:持有全部策略的引用,當收到請求時委派給對應合適的策略處理並返回結果。
  • 抽象策略(Strategy)角色:這是一個抽象角色,一般由一個接口或抽象類實現。
  • 具體策略(ConcreteStrategy)角色:包裝了相關的算法或行爲。

如今咱們回到委派模式,其實跟策略模式很像,區別就是委派模式的 DispatcherServlet 持有全部的委託類引用。

場景使用

假設如今 Boss 點子來了想作一個根據手機外殼來改變 app 主題樣式功能。這個時候就把任務交給了產品經理 ,產品經理就找來程序猿委託開發小哥哥去分工實現。這樣Boss就是一個請求,而產品經理就是一個 dispatcherSevlet 。

boss把任務給 leader, 而 leader 作了一個任務的分配和調度的工做,本身沒有作工做,而是把具體工做交給具體的執行者去作。

代碼實現以下

首先定義咱們的任務執行角色,以及各自分工任務的程序猿

/** * 執行的接口 */
public interface IExcuter {
    void execute(String command);
}

/** * 程序猿A執行的工做 */
public class ExcuterA implements IExcuter {

    @Override
    public void execute(String command) {
        System.out.println("員工A 開始作" + command + "的工做");
    }
}

/** * 程序猿B執行的任務 */
public class ExcuterB implements IExcuter {
    @Override
    public void execute(String command) {
        System.out.println("員工B 開始作" + command + "的工做");
    }
}
複製代碼

接着定義咱們的 產品經理

/** * @description: leader 委派者 任務分發的做用 * @ModificationHistory who when What **/
public class LeaderDispatch {

    private Map<String, IExcuter> targets = new HashMap<String, IExcuter>();

    public Leader() {
        targets.put("識別顏色", new ExcuterA());
        targets.put("切換主題", new ExcuterB());
    }

    
    public void dispatch (String command) {
        //根據指令委託到對應的執行者
        targets.get(command).execute(command);
    }
}
複製代碼

最後咱們模擬boss發送指令實現功能

public class Boss {
    public static void main(String[] args) {
        LeaderDispatch leader = new LeaderDispatch();
        //看上去好像是咱們的項目經理在幹活
        //但實際幹活的人是普通員工
        //這就是典型,幹活是個人,功勞是你的
        leader.execute("識別顏色");
        leader.execute("切換主題");
    }
}
複製代碼

最後咱們查看打印結果

員工B 開始作登陸的工做
員工A 開始作加密的工做

複製代碼

總結

經過此文咱們從新複習了策略模式,經過策略模式演化出委託模式。

Spring MVC框架中的DispatcherServlet其實就是用到的委派模式,針對以前的MVC執行流程沒法理解的HandlerMapping其實就是這裏的項目經理維護的各個員工的信息。

上述實例中,爲了簡單,直接在構造函數中維護了相關實例的引用,可是在具體的HandlerMapping 中,這一步顯然要複雜的多。

關注、轉發、點贊收藏,個人兩小時編寫換你一秒的隨手關注、轉發、點贊收藏

JavaStorm
相關文章
相關標籤/搜索