委派模式

委派模式的定義及應(yīng)用場(chǎng)景

委派模式不屬于 GOF23 種設(shè)計(jì)模式中。委派模式(Delegate Pattern)的基本作用就是 負(fù)責(zé)任務(wù)的調(diào)用和分配任務(wù)班挖,跟代理模式很像,可以看做是一種特殊情況下的靜態(tài)代理 的全權(quán)代理芯砸,但是代理模式注重過(guò)程萧芙,而委派模式注重結(jié)果。委派模式在 Spring 中應(yīng)用 非常多假丧,大家常用的 DispatcherServlet 其實(shí)就是用到了委派模式∷荆現(xiàn)實(shí)生活中也常有委 派的場(chǎng)景發(fā)生,例如:老板(Boss)給項(xiàng)目經(jīng)理(Leader)下達(dá)任務(wù)包帚,項(xiàng)目經(jīng)理會(huì)根據(jù) 實(shí)際情況給每個(gè)員工派發(fā)工作任務(wù)渔期,待員工把工作任務(wù)完成之后,再由項(xiàng)目經(jīng)理匯報(bào)工 作進(jìn)度和結(jié)果給老板渴邦。我們用代碼來(lái)模擬下這個(gè)業(yè)務(wù)場(chǎng)景擎场,先來(lái)看一下類圖:


創(chuàng)建 IEmployee 員工接口:

public interface IEmployee {

    public void doing(String command);

}

創(chuàng)建員工 EmployeeA 類:

public class EmployeeA implements IEmployee {
    @Override
    public void doing(String command) {
        System.out.println("我是員工A羽德,我現(xiàn)在開(kāi)始干" + command + "工作");
    }
}

創(chuàng)建員工 EmployeeB 類:

public class EmployeeB implements IEmployee {
    @Override
    public void doing(String command) {
        System.out.println("我是員工B,我現(xiàn)在開(kāi)始干" + command + "工作");
    }
}

創(chuàng)建項(xiàng)目經(jīng)理 Leader 類:

public class Leader implements IEmployee {

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

    public Leader() {
        targets.put("加密",new EmployeeA());
        targets.put("登錄",new EmployeeB());
    }

    //項(xiàng)目經(jīng)理自己不干活
    public void doing(String command){
        targets.get(command).doing(command);
    }

}

創(chuàng)建 Boss 類下達(dá)命令:

public class Boss {

    public void command(String command,Leader leader){
        leader.doing(command);
    }

}

測(cè)試代碼:

public class DelegateTest {

    public static void main(String[] args) {

        //客戶請(qǐng)求(Boss)迅办、委派者(Leader)宅静、被被委派者(Target)
        //委派者要持有被委派者的引用
        //代理模式注重的是過(guò)程, 委派模式注重的是結(jié)果
        //策略模式注重是可擴(kuò)展(外部擴(kuò)展)站欺,委派模式注重內(nèi)部的靈活和復(fù)用
        //委派的核心:就是分發(fā)姨夹、調(diào)度、派遣

        //委派模式:就是靜態(tài)代理和策略模式一種特殊的組合

        new Boss().command("登錄",new Leader());

    }

}

通過(guò)上面的代碼矾策,生動(dòng)地還原了項(xiàng)目經(jīng)理分配工作的業(yè)務(wù)場(chǎng)景磷账,也是委派模式的生動(dòng)體現(xiàn)。

委派模式在源碼中的體現(xiàn)

下面我們?cè)賮?lái)還原一下 SpringMVC 的 DispatcherServlet 是如何實(shí)現(xiàn)委派模式的贾虽。創(chuàng)建 業(yè)務(wù)類 MemberController:

public class MemberController {

    public void getMemberById(String mid){

    }

}

OrderController 類:

public class OrderController {

    public void getOrderById(String mid){

    }

}

SystemController 類:

public class SystemController {

    public void logout(){

    }

}

創(chuàng)建 DispatcherServlet 類:

/**
 * 相當(dāng)于是項(xiàng)目經(jīng)理的角色
 * Created by Tom.
 */
public class DispatcherServlet extends HttpServlet{

    private List<Handler> handlerMapping = new ArrayList<Handler>();

    public void init() throws ServletException {
        try {
            Class<?> memberControllerClass = MemberController.class;
            handlerMapping.add(new Handler()
                    .setController(memberControllerClass.newInstance())
                    .setMethod(memberControllerClass.getMethod("getMemberById", new Class[]{String.class}))
                    .setUrl("/web/getMemberById.json"));
        }catch(Exception e){

        }
    }

//    private void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception{
//
//        String uri = request.getRequestURI();
//
//        String mid = request.getParameter("mid");
//
//        if("getMemberById".equals(uri)){
//            new MemberController().getMemberById(mid);
//        }else if("getOrderById".equals(uri)){
//            new OrderController().getOrderById(mid);
//        }else if("logout".equals(uri)){
//            new SystemController().logout();
//        }else {
//            response.getWriter().write("404 Not Found!!");
//        }
//
//    }


    private void doDispatch(HttpServletRequest request, HttpServletResponse response){

        //1逃糟、獲取用戶請(qǐng)求的url
        //   如果按照J(rèn)2EE的標(biāo)準(zhǔn)、每個(gè)url對(duì)對(duì)應(yīng)一個(gè)Serlvet蓬豁,url由瀏覽器輸入
       String uri = request.getRequestURI();

        //2绰咽、Servlet拿到url以后,要做權(quán)衡(要做判斷地粪,要做選擇)
        //   根據(jù)用戶請(qǐng)求的URL取募,去找到這個(gè)url對(duì)應(yīng)的某一個(gè)java類的方法

        //3、通過(guò)拿到的URL去handlerMapping(我們把它認(rèn)為是策略常量)
        Handler handle = null;
        for (Handler h: handlerMapping) {
            if(uri.equals(h.getUrl())){
                handle = h;
                break;
            }
        }

        //4蟆技、將具體的任務(wù)分發(fā)給Method(通過(guò)反射去調(diào)用其對(duì)應(yīng)的方法)
        Object object = null;
        try {
            object = handle.getMethod().invoke(handle.getController(),request.getParameter("mid"));
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

        //5玩敏、獲取到Method執(zhí)行的結(jié)果,通過(guò)Response返回出去
//        response.getWriter().write();

    }


    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        try {
            doDispatch(req,resp);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    class Handler{

        private Object controller;
        private Method method;
        private String url;

        public Object getController() {
            return controller;
        }

        public Handler setController(Object controller) {
            this.controller = controller;
            return this;
        }

        public Method getMethod() {
            return method;
        }

        public Handler setMethod(Method method) {
            this.method = method;
            return this;
        }

        public String getUrl() {
            return url;
        }

        public Handler setUrl(String url) {
            this.url = url;
            return this;
        }
    }


}

配置 web.xml 文件:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:javaee="http://java.sun.com/xml/ns/javaee"
    xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
    version="2.4">
    <display-name>Gupao Web Application</display-name>


    <servlet>
        <servlet-name>delegateServlet</servlet-name>
        <servlet-class>com.gupaoedu.vip.pattern.delegate.mvc.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>delegateServlet</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>


</web-app>

一個(gè)完整的委派模式就實(shí)現(xiàn)出來(lái)了质礼。當(dāng)然旺聚,在 Spring 中運(yùn)用到委派模式不僅于此,還有 很多眶蕉。小伙伴們可以通過(guò)命名就可以識(shí)別翻屈。在 Spring 源碼中妻坝,只要以 Delegate 結(jié)尾的 都是實(shí)現(xiàn)了委派模式伸眶。例如:BeanDefinitionParserDelegate 根據(jù)不同類型委派不同的 邏輯解析 BeanDefinition。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末刽宪,一起剝皮案震驚了整個(gè)濱河市厘贼,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌圣拄,老刑警劉巖嘴秸,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡岳掐,警方通過(guò)查閱死者的電腦和手機(jī)凭疮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)串述,“玉大人执解,你說(shuō)我怎么就攤上這事「傩铮” “怎么了衰腌?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)觅赊。 經(jīng)常有香客問(wèn)我右蕊,道長(zhǎng),這世上最難降的妖魔是什么吮螺? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任饶囚,我火速辦了婚禮,結(jié)果婚禮上鸠补,老公的妹妹穿的比我還像新娘萝风。我一直安慰自己,他們只是感情好莫鸭,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著横殴,像睡著了一般被因。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上衫仑,一...
    開(kāi)封第一講書(shū)人閱讀 51,754評(píng)論 1 307
  • 那天梨与,我揣著相機(jī)與錄音,去河邊找鬼文狱。 笑死粥鞋,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的瞄崇。 我是一名探鬼主播呻粹,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼苏研!你這毒婦竟也來(lái)了等浊?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤摹蘑,失蹤者是張志新(化名)和其女友劉穎筹燕,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡撒踪,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年过咬,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片制妄。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡掸绞,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出忍捡,到底是詐尸還是另有隱情集漾,我是刑警寧澤,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布砸脊,位于F島的核電站具篇,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏凌埂。R本人自食惡果不足惜驱显,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望瞳抓。 院中可真熱鬧埃疫,春花似錦、人聲如沸孩哑。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)横蜒。三九已至胳蛮,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間丛晌,已是汗流浹背仅炊。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留澎蛛,地道東北人抚垄。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像谋逻,于是被迫代替她去往敵國(guó)和親呆馁。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 委派模式 委派模式不屬于GOF23種設(shè)計(jì)模式中毁兆。委派模式(DelegatePattern)的基本作用就是負(fù)責(zé)任務(wù)的...
    javacoo閱讀 239評(píng)論 0 1
  • 委派模式其實(shí)并不是常用的二十三種設(shè)計(jì)模式智哀,它是代理模式和策略模式的組合使用。 舉個(gè)例子:比如說(shuō)荧恍,boss將任務(wù)委派...
    iarchitect閱讀 280評(píng)論 0 0
  • 1.委派模式簡(jiǎn)介 在常用的23種設(shè)計(jì)模式中其實(shí)面沒(méi)有委派模式(delegate)的影子瓷叫,但是在Spring中委派模...
    Mrsunup閱讀 10,227評(píng)論 10 11
  • 委派模式(delegate)的基本作用就是負(fù)責(zé)任務(wù)的調(diào)度和分配屯吊,它和代理模式很像但是委派模式注重的是結(jié)果,而代理模...
    _太陽(yáng)神_閱讀 194評(píng)論 0 1
  • 類似于:老板將工作給了項(xiàng)目經(jīng)理摹菠,項(xiàng)目經(jīng)理委托給不同的員工盒卸,但是項(xiàng)目經(jīng)理與員工實(shí)現(xiàn)相同的接口,調(diào)用相同的方法次氨,只是項(xiàng)...
    守拙者_(dá)6a98閱讀 363評(píng)論 0 0