基本作用就是负责任务的调度和分配任务,跟代理模式很像,可以看做是一种特殊情况下的静态代理的全权代理,但是代理模式注重过程,而委派模式注重结果。
不属于gof23种设计模式之一。
属于行为型模式。
现实场景:
老板要做一些事情,只需要交代给经理,由经理分发给对应的员工即可
代码:
/**
* @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());
}
}
分析一下,老板相当于需求,现在有一个经理类来帮老板分发任务,所以经理需要知道所有员工,以及每个员工对应的任务,用一个私有的map存了所有员工以及对应的任务,当收到一个任务时,可以很快的安排对应的任务给对应的员工,这种模式有点像静态代理。
类之间的关系:
那么问题来了,我们写代码到底在哪里会用到委派模式呢,不急我们先来看一段代码,看完你就知道了。
/**
* @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{
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;
}
}
}