java设计模式————委派模式,天天使用却不知道的模式,手撸spring

委派模式(Delegate Pattern): 基本作用就是负责任务的调度和分配任务,跟代理模式很像,可以看做是一种特殊情况下的静态代理的全权代理,但是代理模式注重过程,而委派模式注重结果。
不属于gof23种设计模式之一。
属于行为型模式。
现实场景:
老板要做一些事情,只需要交代给经理,由经理分发给对应的员工即可
【java设计模式————委派模式,天天使用却不知道的模式,手撸spring】java设计模式————委派模式,天天使用却不知道的模式,手撸spring
文章图片

代码:

/** * @Author Darker * @Descrption 老板 * @Date : Created in 10:37 2020-3-12 */ public class Boss {//委派什么任务给经理 public void delegate(String task,Leader leader){ leader.doing(task); } }/** * @Author Darker * @Descrption被委派的经理,存储他统管的所有员工 * @Date : Created in 10:37 2020-3-12 */ public class Leader { //要知道每个员工的特长何特征 private Map register = new HashMap<>(); public Leader(){ register.put("数据库",new Aemployee()); register.put("业务逻辑",new Bemployee()); }//分配对应的任务给对应的员工 public void doing(String task){ register.get(task).doingSomeThings(task); } }/** * @Author Darker * @Descrption 员工抽象 * @Date : Created in 10:38 2020-3-12 */ public interface IEmployee {public void doingSomeThings(String task); }/** * @Author Darker * @Descrption * @Date : Created in 10:39 2020-3-12 */ public class Aemployee implements IEmployee{ @Override public void doingSomeThings(String task) { System.out.println("我是a员工,我负责做数据库的工作,我做了"+task+"任务"); } }/** * @Author Darker * @Descrption * @Date : Created in 10:40 2020-3-12 */ public class Bemployee implements IEmployee{ @Override public void doingSomeThings(String task) { System.out.println("我是b员工,我负责做业务开发的工作,我做了"+task+"任务"); } }

执行结果:
现在老板需要委派一个数据库的任务给经理,获得反馈
/** * @Author Darker * @Descrption * @Date : Created in 10:57 2020-3-12 */ public class DelegateTest { public static void main(String[] args) { new Boss().delegate("数据库",new Leader()); } }

java设计模式————委派模式,天天使用却不知道的模式,手撸spring
文章图片

分析一下,老板相当于需求,现在有一个经理类来帮老板分发任务,所以经理需要知道所有员工,以及每个员工对应的任务,用一个私有的map存了所有员工以及对应的任务,当收到一个任务时,可以很快的安排对应的任务给对应的员工,这种模式有点像静态代理。
类之间的关系:

java设计模式————委派模式,天天使用却不知道的模式,手撸spring
文章图片


那么问题来了,我们写代码到底在哪里会用到委派模式呢,不急我们先来看一段代码,看完你就知道了。
/** * @Author Darker * @Descrption 请求处理Servlet * @Date : Created in 11:14 2020-3-12 */ public class DispatcherServlet extends HttpServlet{@Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { delegate(req,resp); }public void delegate(HttpServletRequest req, HttpServletResponse resp){ String reqUrl = req.getRequestURI(); if ("getOrderById".equals(reqUrl)){ new OrderController().getOrderById(); }else if("logout".equals(reqUrl)){ new SystemController().logout(); }else{ System.out.println("访问路径不存在 404"); } } }/** * @Author Darker * @Descrption 订单业务Controller * @Date : Created in 11:15 2020-3-12 */ public class OrderController {public void getOrderById(){} }/** * @Author Darker * @Descrption 系统操作Controller * @Date : Created in 11:28 2020-3-12 */ public class SystemController {public void logout(){} }

发现了没有,我们浏览器输入的访问地址都是走servlet,然后servlet来帮我们分派到你要调用的service中并且决定调用哪一个方法,这是不是就是策略模式呢,我们上面写的代码就是一个简易的分配逻辑。
好了,这就是委派模式了,它是一种比较简单的设计模式,但是和其它模式结合在一起也对代码的优化起到了不可忽视的作用。
补充:
上面最后的处理有点粗糙,所以本人参考spring的源码又做了些补充,是学习spring的思想来写的,下面是改进后的代码。
/** * @Author Darker * @Descrption 请求处理Servlet * @Date : Created in 11:14 2020-3-12 */ public class DispatcherServlet extends HttpServlet{private List handlerMapping = new ArrayList<>(); //初始化的时候把controller和访问路径,方法绑定在一个list里面 @Override public void init() throws ServletException { Class orderControllerClass =OrderController.class; try { handlerMapping.add(new Handler() .setController(orderControllerClass.newInstance()) .setMeThod(orderControllerClass.getMethod("getOrderById")) .setUrl("/web/getMemberById.json") ); } catch (Exception e) { e.printStackTrace(); }}@Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { delegate(req,resp); }public void delegate(HttpServletRequest req, HttpServletResponse resp){ String reqUrl = req.getRequestURI(); Handler handler = null; for(Handler h :handlerMapping){ if(reqUrl.equals(h.getUrl())){ handler = h; break; } }try { Object o = handler.getMeThod().invoke(handler.getController(),null); try { resp.getWriter().write(o.toString()); } catch (IOException e) { e.printStackTrace(); } } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); }/* if ("getOrderById".equals(reqUrl)){ new OrderController().getOrderById(); }else if("logout".equals(reqUrl)){ new SystemController().logout(); }else{ System.out.println("访问路径不存在 404"); }*/ }//绑定的类,模仿lombok的链式调用 class Handler{ privateObject 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; } } }


    推荐阅读