设计模式之委派模式(Delegate Pattern),不属于 23种设计模式
文章目录一、委派模式的定义二、优缺点三、区别代码模式 与 委派模式的区别四、角色与UML类图4.1、主要角色:4.2、UML类图五、示例1:5.1、参考类图:5.2、代码:1、BaseService( 任务接口)2、具体任务(FrontService、BackendService)3、Delegator:委派者角色4、Client5、效果截图:六、示例26.1、需求:6.2、代码:1、Worker
一、委派模式的定义
委派模式的基本作用是负责任务的调度和分配任务。
委派模式
在现实生活中也有相关的体现,比如一个具体任务的执行,首先是经过高层领导讨论,将具体的任务委派给相关部门经理,部门经理拿到任务通知后去委派相关的员工具体执行任务,委派任务的角色实际并非具体执行任务,而是对任务分发,执行过程进行管理。
委派模式
是一种行为型模式。 在Spring 中应用挺多的,但是不属于(GOF)23种设计模式。
二、优缺点
优点:
对内隐藏实现, 简化调用。
缺点:
当实际处理业务的类需要扩展时,派发命令的类也需要对应做调整,不符合开闭原则。
三、区别
代理模式 与 委派模式的区别
代理模式 注重的是 过程, 委派模式 注重的是 结果;
策略模式 注重是可扩展(外部扩展),委派模式 注重内部的灵活和复用;
委派的核心:就是分发、调度、派遣;
委派模式:就是静态代理和策略模式一种特殊的组合;
四、角色与UML类图
4.1、主要角色:
-
Task
(抽象任务): 定义一个抽象接口, 它有多个实现类。 -
ConcreteTask
(具体任务执行者、被委派者): 真正执行任务的角色。 -
Delegate
(委派者): 负责在各个具体角色实例之间做出决策,判断并调用ConcreteTask
的方法。
4.2、UML类图
说明: 有的书上说 Delegate
不实现 Task
接 口 。
五、示例1:
5.1、参考类图:
5.2、代码:
1、BaseService( 任务接口)
/**
* 公共的服务接口
*/
public interface BaseService {
// 执行命令的方法
void execute();
}
2、具体任务(FrontService、BackendService)
前台Service:
/**
* 前台Service
*/
public class FrontService implements BaseService {
@Override
public void execute() {
System.out.println("执行前端页面设计任务");
}
}
后台Service:
/**
* 后台Service
*/
public class BackendService implements BaseService {
@Override
public void execute() {
System.out.println("执行后台代码开发任务");
}
}
3、Delegator:委派者角色
委派者角色,负责委派,分发任务,最后提交执行的结果。
import java.util.HashMap;
import java.util.Map;
/**
* 委派任务角色
*/
public class Delegator {
/** 用一个容器存放不同的子任务对应的执行对象*/
Map<String, BaseService> map = new HashMap<>();
// 任务的委派,分发
private BaseService delegate(String msg) {
map.put("font", new FrontService());
map.put("backend", new BackendService());
if ("backend".equals(msg)) {
return map.get(msg);
} else if ("font".equals(msg)) {
return map.get(msg);
}
System.out.println("委派任务出错!");
return null;
}
// 任务具体的执行
public void execute(String msg) {
if (delegate(msg)!=null) {
delegate(msg).execute();
}
}
}
4、Client
/**
* 客户端 ->委派任务
*/
public class Client {
public static void main(String[] args) {
String command1 = "font";
String command2 = "backend";
String command3 = "test";
Delegator delegator = new Delegator();
delegator.execute(command1);
delegator.execute(command2);
delegator.execute(command3);
}
}
5、效果截图:
执行前端页面设计任务
执行后台代码开发任务
委派任务出错!
六、示例2
6.1、需求:
老板( Boss ) 给 组长 ( Leader ) 下达任务,组长 ( Leader ) 根据实际情况给每个员工派发工作任务, 等到员工把工作任务完成之后, 再由组长 ( Leader ) 将 汇报工作进度和结果给 老板( Boss )。
6.2、代码:
1、Worker:委派者和被委派者共同的接口
实现一个 Worker
接口,这个是作为 委派者 和 被委派者 共同的接口。
/**
* 工人接口
*/
public interface Worker {
void doing(String thing);
}
2、普通工人( 厨师工、缝纫工 ):被委派者
/**
* 厨师工
*/
public class ChefWorker implements Worker {
@Override
public void doing(String thing) {
System.out.println("我是厨师,我接到任务,需要做美食。");
}
}
/**
* 缝纫工
*/
public class TailorWorker implements Worker {
@Override
public void doing(String thing) {
System.out.println("我是缝纫工,我接到任务,需要做衣服。");
}
}
3、组长 (Leader
): 委派发者
/**
* 组长
*/
public class Leader implements Worker {
private static Map<String, Worker> workerMap = new HashMap<>();
public Leader() {
workerMap.put("cooking", new ChefWorker());
workerMap.put("sewing", new TailorWorker());
}
/**
* 做事情
*
* @param thing 任务
*/
@Override
public void doing(String thing) {
System.out.println("我是组长,老板派活了: " + thing + ",我来安排任务: " + thing);
if (workerMap.containsKey(thing)) {
workerMap.get(thing).doing(thing);
} else {
System.err.println("目前办公室没有对应职位的工人");
}
}
}
4、老板 (Boss
) 下命令:
老板( Boss
)将工作分给组长。
/**
* 领导
*/
public class Boss {
/**
* 下命令
*
* @param thing 需要处理的事情
* @param leader 安排给一个组长
*/
public void command(String thing, Leader leader) {
System.out.println("我是老板,我现在需要处理: " + thing);
leader.doing(thing);
}
}
5、Client
/**
* 测试类
*/
public class Client {
public static void main(String[] args) {
Boss boss = new Boss();
// 做饭
boss.command("cooking", new Leader());
System.out.println("================================");
// 缝纫
boss.command("sewing", new Leader());
// 销售
System.out.println("================================");
boss.command("selling", new Leader());
}
}
6、运行结果:
我是老板,我现在需要处理: cooking
我是组长,老板派活了: cooking,我来安排任务: cooking
我是厨师,我接到任务,需要做美食。
================================
我是老板,我现在需要处理: sewing
我是组长,老板派活了: sewing,我来安排任务: sewing
我是缝纫工,我接到任务,需要做衣服。
================================
我是老板,我现在需要处理: selling
我是组长,老板派活了: selling,我来安排任务: selling
目前办公室没有对应职位的工人
七、委派模式 在开源框架中的使用
委派模式大量使用在spring、mybatis等开源框架中,理解委派模式的实现原理可以更好理解这些框架源码。委派模式的核心是 委派类
的实现 。
代码中,一般 Delegate
、Dispatcher
结尾的都是委派类。
在Spring源码中我们可以搜索一下,使用 delegate
关键词模糊查找到如下的类:
BeanDefinitionParserDelegate
、ConstructorDelegate
、 MultipartResolutionDelegate
、TypeConverterDelegate
等。
我们熟知的 DispatcherServlet
虽然没带 delegate
,但也是委派模式的一种实现。
前端请求都统一走到 DispatcherServlet
的 doService()
方法中,然后在 doService()
方法中调用 doDispatch()
方法,在 doDispatch()
方法中,进行复杂的任务进行分解,分发执行并通过一个委派者角色,会获取业务处理的 handler
,执行 handle()
方法处理请求结果。
DispatcherServlet
的 doDispatch()
方法截图:
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)