委派模式

委派模式的定義及應用場景

委派模式不屬于 GOF23 種設計模式中。委派模式(Delegate Pattern)的基本作用就是 負責任務的調用和分配任務,跟代理模式很像,可以看做是一種特殊情況下的靜態(tài)代理 的全權代理,但是代理模式注重過程,而委派模式注重結果。委派模式在 Spring 中應用 非常多,大家常用的 DispatcherServlet 其實就是用到了委派模式?,F(xiàn)實生活中也常有委 派的場景發(fā)生,例如:老板(Boss)給項目經理(Leader)下達任務,項目經理會根據(jù) 實際情況給每個員工派發(fā)工作任務,待員工把工作任務完成之后,再由項目經理匯報工 作進度和結果給老板。我們用代碼來模擬下這個業(yè)務場景,先來看一下類圖:


創(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)在開始干" + command + "工作");
    }
}

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

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

創(chuà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());
    }

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

}

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

public class Boss {

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

}

測試代碼:

public class DelegateTest {

    public static void main(String[] args) {

        //客戶請求(Boss)、委派者(Leader)、被被委派者(Target)
        //委派者要持有被委派者的引用
        //代理模式注重的是過程, 委派模式注重的是結果
        //策略模式注重是可擴展(外部擴展),委派模式注重內部的靈活和復用
        //委派的核心:就是分發(fā)、調度、派遣

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

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

    }

}

通過上面的代碼,生動地還原了項目經理分配工作的業(yè)務場景,也是委派模式的生動體現(xiàn)。

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

下面我們再來還原一下 SpringMVC 的 DispatcherServlet 是如何實現(xiàn)委派模式的。創(chuàng)建 業(yè)務類 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 類:

/**
 * 相當于是項目經理的角色
 * 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、獲取用戶請求的url
        //   如果按照J2EE的標準、每個url對對應一個Serlvet,url由瀏覽器輸入
       String uri = request.getRequestURI();

        //2、Servlet拿到url以后,要做權衡(要做判斷,要做選擇)
        //   根據(jù)用戶請求的URL,去找到這個url對應的某一個java類的方法

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

        //4、將具體的任務分發(fā)給Method(通過反射去調用其對應的方法)
        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í)行的結果,通過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>

一個完整的委派模式就實現(xiàn)出來了。當然,在 Spring 中運用到委派模式不僅于此,還有 很多。小伙伴們可以通過命名就可以識別。在 Spring 源碼中,只要以 Delegate 結尾的 都是實現(xiàn)了委派模式。例如:BeanDefinitionParserDelegate 根據(jù)不同類型委派不同的 邏輯解析 BeanDefinition。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 委派模式 委派模式不屬于GOF23種設計模式中。委派模式(DelegatePattern)的基本作用就是負責任務的...
    javacoo閱讀 294評論 0 1
  • 委派模式其實并不是常用的二十三種設計模式,它是代理模式和策略模式的組合使用。 舉個例子:比如說,boss將任務委派...
    iarchitect閱讀 316評論 0 0
  • 1.委派模式簡介 在常用的23種設計模式中其實面沒有委派模式(delegate)的影子,但是在Spring中委派模...
    Mrsunup閱讀 10,366評論 10 11
  • 委派模式(delegate)的基本作用就是負責任務的調度和分配,它和代理模式很像但是委派模式注重的是結果,而代理模...
    _太陽神_閱讀 210評論 0 1
  • 類似于:老板將工作給了項目經理,項目經理委托給不同的員工,但是項目經理與員工實現(xiàn)相同的接口,調用相同的方法,只是項...
    守拙者_6a98閱讀 419評論 0 0

友情鏈接更多精彩內容