手撸设计模式之-委派模式
手撸设计模式之-委派模式
- 一 、委派模式介绍
- 1.1 定义
- 1.2 委派模式结构
- 1.3 委派模式UML结构图
- 1.4 委派模式代码实现
- 二、委派模式场景
- 2.1 场景定义
- 2.2 场景描述图
- 2.4 MVC委派模式核心源码截图
- 2.3 委派模式场景UML结构图
- 2.3 委派模式场景代码实现
- 2.4 委派模式优点
- 2.5 委派模式缺点
- 三、总结
一 、委派模式介绍
1.1 定义
在23种设计模式中不包含委派模式(delegate),但是在很多框架中都大量使用委派模式,比如Spring,Mybatis等框架。
委派模式基本作用就是负责任务的调用和分类任务,类似代理模式这种形式,可以看作是一个特殊的静态代理的全权代理,但是代理模式很注重过程,而委派模式注重结果。
委派模式在Spring中的体现:SpringMVC框架中DispathServlet的实现,充分体现了委派模式用法。
1.2 委派模式结构
实现层面上, 定义一个抽象接口, 它有若干实现类, 他们真正执行业务方法, 这些子类是具体任务角色; 定义委派者角色也实现该接口, 但它负责在各个具体角色实例之间做出决策, 由它判断并调用具体实现的方法。
委派模式主要有以下角色:
抽象任务角色(AbstractTssk): 主要定义抽象任务接口
委派者角色(DelegateTask): 负责在各个具体角色之间做出决策,执行委派操作。
具体任务角色(ConcreteTask): 实现抽象任务角色的业务逻辑,即是具体执行操作。
1.3 委派模式UML结构图
1.4 委派模式代码实现
抽象任务接口定义:
public interface Task {void doTask();
}
委派任务对象定义:
public class Delegate implements Task {/*** 根据业务委派具体执行对象*/@Overridepublic void doTask() {System.out.println("全权代理模式开始执行...");Task task = null;//可以使用策略模式优化if (new Random().nextBoolean()) {task = new ConcreteTaskA();task.doTask();} else {task = new ConcreteTaskB();task.doTask();}System.out.println("全权代理模式执行完成...");}
}
具体执行业务A定义:
public class ConcreteTaskA implements Task {@Overridepublic void doTask() {System.out.println("执行任务 A操作");}
}
具体执行业务B定义:
public class ConcreteTaskB implements Task {@Overridepublic void doTask() {System.out.println("执行任务 B操作");}
}
测试客户端类定义:
public class ClientDelegate {public static void main(String[] args) {new Delegate().doTask();}
}
预期输出结果定义:
全权代理模式开始执行...
执行任务 B操作
全权代理模式执行完成...
二、委派模式场景
2.1 场景定义
委派模式就是一个负责任务的调用和分配的类,比如在SpringMVC中我们熟悉的DispatcherServlet。前端请求都统一走到DispatcherServlet 的doService()方法中,然后在doService()方法中调用doDispatch()方法,在doDispatch()方法中,会获取业务处理的handler,执行handle()方法处理请求。
2.2 场景描述图
描述SpringMVC中HandlerMapping处理器实现委派过程。
2.4 MVC委派模式核心源码截图
2.3 委派模式场景UML结构图
2.3 委派模式场景代码实现
抽象handlerMapping接口定义:
public interface HandlerMapping {HandlerMapping getHandler();
}
url路径处理映射定义:
public class UrlHandlerMapping implements HandlerMapping {@Overridepublic HandlerMapping getHandler() {System.out.println("UrlHandlerMapping.getHandler");return null;}
}
请求方法处理映射定义:
public class MethodHandlerMapping implements HandlerMapping {@Overridepublic HandlerMapping getHandler() {System.out.println("MethodHandlerMapping.getHandler");return null;}
}
请求中央处理器定义:
public class DispatcherServlet {private Map<String, HandlerMapping> handlerMappings;public DispatcherServlet() {this.handlerMappings = new HashMap<>(2);this.initHandlerMappings();}/*** 初始化HandlerMapping*/private void initHandlerMappings() {this.handlerMappings.put("method", new MethodHandlerMapping());this.handlerMappings.put("url", new UrlHandlerMapping());}/*** 模拟具体调度方法** @param handlerMapping 处理映射器*/public void doDispatch(String handlerMapping) {this.handlerMappings.get(handlerMapping).getHandler();}
}
测试Controller定义:
public class TestController {public String test(String handler) {DispatcherServlet dispatcherServlet = new DispatcherServlet();dispatcherServlet.doDispatch(handler);return "模拟调用处理器映射器";}
}
测试用例定义:
@Testpublic void test() {TestController testController = new TestController();testController.test("url");System.out.println("===============");testController.test("method");}
预期输出结果:
UrlHandlerMapping.getHandler
===============
MethodHandlerMapping.getHandler
2.4 委派模式优点
- 对内隐藏实现, 易于扩展; 简化调用;
2.5 委派模式缺点
随着数据越来越多,数据也越来越复杂,维护的类也越来越多,实现类会越来越多,接口也会越来越多,导致程序变得复杂,代码膨胀。
三、总结
在一些框架源码中,比如Spring等,命名一Delegate结尾比如BeanDefinitionParserDelegate(根据不同的类型委派不同的逻辑解析BeanDefinition),或者是以Dispacher开头和结尾或开头的比如DispacherServlet一般都使用了委派模式。
大实话比如:功劳什么的是我的,干活是你的。
代码案例