1.委派模式简介
在常用的23种设计模式中其实面没有委派模式(delegate)的影子,但是在Spring中委派模式确实用的比较多的一种模式。
在spring中的体现:Spring MVC框架中的DispatcherServlet其实就用到了委派模式。
委派模式的作用: 基本作用就是负责任务的调用和分配任务,跟代理模式很像,可以看做是一种特殊情况下的静态代理的全权代理,但是代理模式注重过程,而委派模式注重结果
2.委派模式的实例
先引用一张图来介绍委派模式,下图主要说明了 boss把任务给leader,而leader做了一个任务的分配和调度的工作,自己没有做工作,而是把具体工作交给具体的执行者去做。
委派模式.png
下面直接给出实例:
执行的接口
/**
* @Project: spring
* @description: 执行的接口
* @author: sunkang
* @create: 2018-08-30 23:10
* @ModificationHistory who when What
**/
public interface IExcuter {
void excute(String command);
}
普通员工A
/**
* @Project: spring
* @description: 员工A执行某项命令
* @author: sunkang
* @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: sunkang
* @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: sunkang
* @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: sunkang
* @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("加密");
}
}
测试结果为:
委派模式测试结果.png
3.委派模式的实现mvc的简单实例
思考:
在springmvc访问地址的url
与Controller层配置的url
是如何映射的
Controller层配置的url
如何跟具体的方法
映射的,参数
又是如何绑定
的
猜测:
url的地址可以根据request得到访问url地址,配置的url地址可以根据配置注解得到,这两者的url匹配上了说明映射成功了,除了url是不够的,还需要一个中间对象保存了url和method以及controller对象的信息,可以把这个中年的映射对象放入容器中,然后根据传入的url从容器取出进行匹配,取出来之后就可以根据映射来完成方法的调用了。
下面就简单实现一个mvc调用的例子
模拟controller层
/**
* @Project: spring
* @description: 模拟controller层
* @author: sunkang
* @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;
}
}
}