委派模式(Delegate Pattern)的基本作用就是负责任务的调度和分配任务,跟代理模式很像,可以看做是一种特殊情况下的静态代理的全权代理,但是代理模式注重过程,而委派模式注重结果。
1 不属于GOF 23种设计模式之一。
2 属于行为型模式
3 Delegate 结尾的一般都是委派,Dispatcher
委派模式在 Spring 中应用非常多,常用的 DispatcherServlet 其实就是用到了委派模式
在 Spring 源码中,只要以 Delegate 结尾的都是实现了委派模式。例如:BeanDefinitionParserDelegate 根据不同类型委派不同的
public interface IEmployee { void doing(String command); }
public class EmployeeB implements IEmployee { @Override public void doing(String command) { System.out.println("我是员工B,我现在开始干" + command + "工作"); } }
public class EmployeeA implements IEmployee { @Override public void doing(String command) { System.out.println("我是员工A,我现在开始干" + command + "工作"); } }
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); } }
public class Boss { public void command(String command,Leader leader){ leader.doing(command); } }
public static void main(String[] args) { //客户请求(Boss)、委派者(Leader)、被被委派者(Target) //委派者要持有被委派者的引用 //代理模式注重的是过程, 委派模式注重的是结果 //策略模式注重是可扩展(外部扩展),委派模式注重内部的灵活和复用 //委派的核心:就是分发、调度、派遣 //委派模式:就是静态代理和策略模式一种特殊的组合 new Boss().command("加密", new Leader()); }
SpringMVC:
public class MemberController { public void getMemberById(String mid){ } }
public class OrderController { public void getOrderById(String mid){ } }
public class SystemController { public void logout(){ } }
public class DispatcherServlet extends HttpServlet{ 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!!"); } } protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { try { doDispatch(req,resp); } catch (Exception e) { e.printStackTrace(); } } }
逻辑解析 BeanDefinition
策略模式:
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){ //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返回出去 try { response.getWriter().write(object.toString()); } catch (IOException e) { e.printStackTrace(); } } 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; } }