1.委派模式简介
在常用的23种设计模式中其实面没有委派模式(delegate)的影子,但是在Spring中委派模式确实用的比较多的一种模式。
在spring中的体现:Spring MVC框架中的DispatcherServlet其实就用到了委派模式。
委派模式的作用: 基本作用就是负责任务的调用和分配任务,跟代理模式很像,可以看做是一种特殊情况下的静态代理的全权代理,但是代理模式注重过程,而委派模式注重结果
2.委派模式的实例
先引用一张图来介绍委派模式,下图主要说明了 boss把任务给leader,而leader做了一个任务的分配和调度的工作,自己没有做工作,而是把具体工作交给具体的执行者去做。
下面直接给出实例:
执行的接口
/** * @Project: spring * @description: 执行的接口 * @author: * @create: 2018-08-30 23:10 * @ModificationHistory who when What **/ public interface IExcuter { void excute(String command); }
普通员工A
/** * @Project: spring * @description: 员工A执行某项命令 * @author: * @create: 2018-08-30 23:10 * @ModificationHistory who when What **/ public class ExcuterA implements IExcuter{ @Override public void excute(String command) { System.out.println("员工A 开始做"+command+"的工作"); } }
普通员工B
/** * @Project: spring * @description: 员工B执行某项命令 * @author: * @create: 2018-08-30 23:10 * @ModificationHistory who when What **/ public class ExcuterB implements IExcuter{ @Override public void excute(String command) { System.out.println("员工B 开始做"+command+"的工作"); } }
leader委派者
/** * @Project: spring * @description: leader 委派者 任务分发的作用 * @author: * @create: 2018-08-30 23:11 * @ModificationHistory who when What **/ public class Leader implements IExcuter { private Map<String,IExcuter> targets = new HashMap<String,IExcuter>(); public Leader() { targets.put("加密",new ExcuterA()); targets.put("登录",new ExcuterB()); } @Override public void excute(String command) { targets.get(command).excute(command); } }
boss类模拟调用测试
/** * @Project: spring * @description: boss 模拟客户执行任务 * @author: * @create: 2018-08-30 23:13 * @ModificationHistory who when What **/ public class Boss { public static void main(String[] args) { Leader leader = new Leader(); //看上去好像是我们的项目经理在干活 //但实际干活的人是普通员工 //这就是典型,干活是我的,功劳是你的 leader.excute("登录"); leader.excute("加密"); } }
测试结果为:
3.委派模式的实现mvc的简单实例
思考:
在springmvc 访问地址的url
与Controller层配置的url
是如何映射的
Controller层配置的url
如何跟具体的方法
映射的,参数
又是如何绑定
的
猜测:
url的地址可以根据request得到访问url地址,配置的url地址可以根据配置注解得到,这两者的url匹配上了说明映射成功了,除了url是不够的,还需要一个中间对象保存了url和method以及controller对象的信息,可以把这个中年的映射对象放入容器中,然后根据传入的url从容器取出进行匹配,取出来之后就可以根据映射来完成方法的调用了。
url的地址可以根据request得到访问url地址,配置的url地址可以根据配置注解得到,这两者的url匹配上了说明映射成功了,除了url是不够的,还需要一个中间对象保存了url和method以及controller对象的信息,可以把这个中年的映射对象放入容器中,然后根据传入的url从容器取出进行匹配,取出来之后就可以根据映射来完成方法的调用了。
下面就简单实现一个mvc调用的例子
模拟controller层
/** * @Project: spring * @description: 模拟controller层 * @author: * @create: 2018-09-03 22:20 * @ModificationHistory who when What **/ public class MemberAction { public void getMemberById(String mid){ } }
模拟serlvert得到的请求如何转发,交给具体的controller处理的
/** * @Project: spring * @description: selvelt的任务分发者 ,主要完成url的映射和调用 * @author: sunkang * @create: 2018-09-03 22:21 * @ModificationHistory who when What **/ public class SelvletDispatcher { //这里也可以用map 对象来保存Hanlder对象 private List<Handler> handlerMapping = new ArrayList<Handler>(); public SelvletDispatcher() { //简单实现一个controller的映射 try { Class clazz = MemberAction.class; handlerMapping.add(new Handler() .setController(clazz.newInstance()) .setMethod(clazz.getMethod("getMemberById",new Class[]{String.class})) .setUrl("/web/getMemberById.json") ); } catch (Exception e) { e.printStackTrace(); } } private void doService(HttpServletRequest request, HttpServletResponse response){ doDispatch(request,response); } /** * 请求的分发工作 * @param request * @param response */ private void doDispatch(HttpServletRequest request, HttpServletResponse response) { //1.获取用户请求的url String uri = request.getRequestURI(); Handler handler =null; ////2、根据uri 去handlerMapping找到对应的hanler for(Handler h :handlerMapping){ if(uri.equals(h.getUrl())){ handler = h; break; } } //3.将具体的任务分发给Method(通过反射去调用其对应的方法) Object obj = null; try { obj = handler.getMethod().invoke(handler.getController(),request.getParameter("mid")); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } //4、获取到Method执行的结果,通过Response返回出去 // response.getWriter().write(); } /** * 具体的hanlder对象 */ class Handler{ //controller对象 private Object controller; //controller对象映射的方法 private String url; //ulr对应的方法 private Method method; public Object getController() { return controller; } public Handler setController(Object controller) { this.controller = controller; return this; } public String getUrl() { return url; } public Handler setUrl(String url) { this.url = url; return this; } public Method getMethod() { return method; } public Handler setMethod(Method method) { this.method = method; return this; } } }