委派模式

委派模式的定义及应用场景

委派模式不属于 GOF23 种设计模式中。委派模式(Delegate Pattern)的基本作用就是 负责任务的调用和分配任务,跟代理模式很像,可以看做是一种特殊情况下的静态代理 的全权代理,但是代理模式注重过程,而委派模式注重结果。委派模式在 Spring 中应用 非常多,大家常用的 DispatcherServlet 其实就是用到了委派模式。现实生活中也常有委 派的场景发生,例如:老板(Boss)给项目经理(Leader)下达任务,项目经理会根据 实际情况给每个员工派发工作任务,待员工把工作任务完成之后,再由项目经理汇报工 作进度和结果给老板。我们用代码来模拟下这个业务场景,先来看一下类图:


创建 IEmployee 员工接口:

public interface IEmployee {

    public void doing(String command);

}

创建员工 EmployeeA 类:

public class EmployeeA implements IEmployee {
    @Override
    public void doing(String command) {
        System.out.println("我是员工A,我现在开始干" + command + "工作");
    }
}

创建员工 EmployeeB 类:

public class EmployeeB implements IEmployee {
    @Override
    public void doing(String command) {
        System.out.println("我是员工B,我现在开始干" + command + "工作");
    }
}

创建项目经理 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);
    }

}

创建 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)
        //委派者要持有被委派者的引用
        //代理模式注重的是过程, 委派模式注重的是结果
        //策略模式注重是可扩展(外部扩展),委派模式注重内部的灵活和复用
        //委派的核心:就是分发、调度、派遣

        //委派模式:就是静态代理和策略模式一种特殊的组合

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

    }

}

通过上面的代码,生动地还原了项目经理分配工作的业务场景,也是委派模式的生动体现。

委派模式在源码中的体现

下面我们再来还原一下 SpringMVC 的 DispatcherServlet 是如何实现委派模式的。创建 业务类 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(){

    }

}

创建 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以后,要做权衡(要做判断,要做选择)
        //   根据用户请求的URL,去找到这个url对应的某一个java类的方法

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

        //4、将具体的任务分发给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执行的结果,通过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>

一个完整的委派模式就实现出来了。当然,在 Spring 中运用到委派模式不仅于此,还有 很多。小伙伴们可以通过命名就可以识别。在 Spring 源码中,只要以 Delegate 结尾的 都是实现了委派模式。例如:BeanDefinitionParserDelegate 根据不同类型委派不同的 逻辑解析 BeanDefinition。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 委派模式 委派模式不属于GOF23种设计模式中。委派模式(DelegatePattern)的基本作用就是负责任务的...
    javacoo阅读 1,828评论 0 1
  • 委派模式其实并不是常用的二十三种设计模式,它是代理模式和策略模式的组合使用。 举个例子:比如说,boss将任务委派...
    iarchitect阅读 2,271评论 0 0
  • 1.委派模式简介 在常用的23种设计模式中其实面没有委派模式(delegate)的影子,但是在Spring中委派模...
    Mrsunup阅读 13,473评论 10 11
  • 委派模式(delegate)的基本作用就是负责任务的调度和分配,它和代理模式很像但是委派模式注重的是结果,而代理模...
    _太阳神_阅读 1,468评论 0 1
  • 类似于:老板将工作给了项目经理,项目经理委托给不同的员工,但是项目经理与员工实现相同的接口,调用相同的方法,只是项...
    守拙者_6a98阅读 2,967评论 0 0

友情链接更多精彩内容