什么是委派模式
委派模式为了解决复制任务的调用及分发。现实中简单的委派模式,老板提出一个需求给领导,然后领导根据手下员工所擅长的来分配不通的任务,然后协同完成老板所提出的需求。
场景一:老板,领导,员工
场景图
UML
代码
package com.swh.design.delegate;
public interface IExecuter {
void executer(String com);
}
package com.swh.design.delegate;
public class ExecuterA implements IExecuter{
@Override
public void executer(String com) {
System.out.println("注册");
}
}
package com.swh.design.delegate;
public class ExecuterB implements IExecuter{
@Override
public void executer(String com) {
System.out.println("登录");
}
}
package com.swh.design.delegate;
import java.util.HashMap;
import java.util.Map;
public class Leader implements IExecuter{
public Map<String,IExecuter> executerMap = new HashMap<>();
public Leader() {
executerMap.put("注册",new ExecuterA());
executerMap.put("登录",new ExecuterB());
}
@Override
public void executer(String com) {
executerMap.get(com).executer(com);
}
}
package com.swh.design.delegate;
public class Boss {
public static void main(String[] args) {
Leader leader = new Leader();
leader.executer("注册");
leader.executer("登录");
}
}
老板(BOSS)交给了领导(Leader)两个任务注册、登录,领导有委派给了员工A和员工B。领导看上去是老板和员工之间的一个中介,相当于静态代理一种特殊模式,全权代理。领导在老板眼里他负责干活实际上,他分发给了下面的员工,他分配工作是需要做一种选择,合理的选择才可以,这也是领导的作用所在。
场景二:Spring 中的Dispacher
场景图
代码
package com.swh.design.delegate.spring.controller;
public class MemberController {
public void login(String aa){
}
}
package com.swh.design.delegate.spring.controller;
public class OrderController {
public void order(){
}
}
package com.swh.design.delegate.spring;
import com.swh.design.delegate.spring.controller.MemberController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class ServletDispatcher {
// 维护了所有的Controller与uri的映射信息
List<Handler> handlers = new ArrayList<Handler>();
public ServletDispatcher(List<Handler> handlers) {
Class<MemberController> memberControllerClass = MemberController.class;
try {
handlers.add(
new Handler().setController(memberControllerClass.newInstance())
.setMethod(memberControllerClass.getMethod("login",new Class[]{String.class}))
.setUrl("/member/login")
);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
public void doServlet(HttpServletRequest request, HttpServletResponse response){
doDispatcher(request,response);
}
private void doDispatcher(HttpServletRequest request,HttpServletResponse response){
// 获取用户请求的URL
String requestURI = request.getRequestURI();
// 选择需要分发给哪个控制器
Handler handler = null;
for (Handler h : handlers) {
if(handler.url.equals(requestURI)){
handler = h;
break;
}
}
try {
// 执行控制器 让控制器干活
Object aa = handler.method.invoke(handler.controller, request.getParameter("aa"));
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException 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;
}
}
}
有了Dispatcher做委派分发,用户在浏览器输入的url回调分发到对应的控制器中。以前使用servlet的时候,还需要在Mapping文件中进行配置uri与控制器的映射关系,
<servlet>
<servlet-name>LogOutServlet</servlet-name>
<servlet-class>com.yonyou.mcloud.cas.web.servlet.LogOutServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LogOutServlet</servlet-name>
<url-pattern>/logout</url-pattern>
</servlet-mapping>
但是,Dispatcher解决了这个问题,不需要每写一个控制器都要去配置一下映射关系。