场景
委派模式不属于GOF23种设计模式,委派模式的基本作用就是负责任务的调用和分配,跟代理模式很像,可以看作一种特殊情况下的静态全权代理,但是代理模式注重过程,而委派模式注重结果。
委派模式在Spring中的应用非常多,常用的DispatcherServlet就用到了委派模式。
现实生活中也常有委派的场景,例如老板给项目经理下达任务,经理再给每个员工下达任务,当员工完成任务后,再由项目经理向老板汇报结果。
员工接口:
public interface IEmployee {
void doing(String command);
}
创建员工类A和B:
public class EmployeeA implements IEmployee {
@Override
public void doing(String command) {
System.out.println("我是员工A,我开始干"+command+"工作");
}
}
public class EmployeeB implements IEmployee {
@Override
public void doing(String command) {
System.out.println("我是员工B,我开始干"+command+"工作");
}
}
创建项目经理类Leader:
public class Leader implements IEmployee {
private Map<String,IEmployee> targets=new HashMap<>();
public Leader(){
targets.put("加密",new EmployeeA());
targets.put("登陆",new EmployeeB());
}
@Override
public void doing(String command) {
targets.get(command).doing(command);
}
}
创建Boss类下达命令:
public class Boss {
public void command(String command,Leader leader){
leader.doing(command);
}
}
测试代码如下:
public static void main(String[] args) {
new Boss().command("登陆",new Leader());
}
代理模式注重的是过程,委派模式注重的是结果
策略模式注重可扩展性,委派模式注重内部的灵活性和可复用性
委派模式的核心就是分发、调度、派遣,委派模式是静态代理和策略模式的一种特殊组合
委派模式在源码中的体现
接下来我们还原一下SpringMVC的DispatcherServlet是如何实现委派模式的。
创建业务类MemberController:
public class MemberController {
public void getMemberById(String mid){
}
}
OrderController类如下:
public class OrderController {
public void getOrderById(String mid){
}
}
SystemController类如下:
public class SystemController {
public void logout(){}
}
创建DispatcherServlet类:
//相当于项目经理的角色
public class DispatcherServlet extends HttpServlet {
private void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception{
String uri=request.getRequestURI();
System.out.println("uri: "+uri);
String mid=request.getParameter("mid");
System.out.println("mid: "+mid);
if("/getMemberById".equals(uri)) {
System.out.println("通过mid获取成员");
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!");
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) {
try{
doDispatch(req, resp);
}catch (Exception e){
e.printStackTrace();
}
}
}
配置web.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>delegateServlet</servlet-name>
<servlet-class>_06委派模式.MVC.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>delegateServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
测试结果:
在Spring中还有很多用到委派模式的地方,以Delegate结尾的地方都实现了委派模式。例如BeanDefinitionPareserDelegate,根据不同类型委派不同的逻辑解析BeanDefinition。