theme: vue-pro
这是我参与8月更文挑战的第6天,活动详情查看:8月更文挑战
委派模式,它不属于GOF23种常见模式,它允许对象组合实现与继承相同的代码重用。
一、定义
委派是一种使组合具有与继承一样强大的复用能力的方法。在委派中,处理请求涉及两个对象: 接收对象将操作委派给其委派对象,这类似于将请求延迟到父类的子类。
委派模式跟代理模式很相似,可以看做是一种特殊情况下的静态代理的全权代理。两种模式有本质的区别,代理模式注重过程,而委派模式注重结果。
两者的区别说的很抽象,具体来说:
- 委派模式大致的流程是:你找我,我作为中间人,我不干事,我又根据你的需求/命令去找别人处理。这里强调一个权衡选择的过程。
- 代理模式大致的流程是:你想办一件事情,明确的知道找A就能完成,但是你不找A,你找A的代理人去处理,实际上A的代理人还是去找A去办理的。
委派模式基本的作用就是负责任务的调用和分配任务。在Java
生态中,Spring
框架就用到了委派模式,哪个地方呢,就是大家熟知的DispatcherServlet
。一般来说类名上使用了Delegating
、Dispathcer
单词,大概率也就用到了委派模式。
二、代码实现
这里构想一个干工程的公司,公司里面有Boss、Manager、Worker等角色,Worker具体细分了电工ElectWorker,木工 WoodWorker等。
有一个场景,老板发送个指令给经理,让经理去安排电工或木工的活。
首先要创建工人的抽象接口,接口中包含描述工人的工种性质,以及工人执行干活的操作。
public interface Worker { /** * 干事的工种类型 * @return 工种类型 */ String workType(); /** * 干事当然是干事情 */ void doingJob(String command); }
然后具体实现木工和电工。
public class WoodWorker implements Worker{ /** * 干事的工种类型 * * @return 工种类型 */ @Override public String workType() { return "WoodWorker"; } /** * 干事当然是干事情 */ @Override public void doingJob(String command) { System.out.println("i am WoodWorker,receive command【 " + command + "】,start to work"); } } public class ElectWorker implements Worker{ /** * 干事的工种类型 * * @return 工种类型 */ @Override public String workType() { return "ElectWorker"; } /** * 干事当然是干事情 */ @Override public void doingJob(String command) { System.out.println("i am ElectWorker,receive command【 " + command + "】,start to work"); } }
管理工人的直接上级是经理。
public class Manager { final Map<String,Worker> scheduler = new HashMap<>(); public Manager(){ scheduler.put(WorkType.WOOD,new WoodWorker()); scheduler.put(WorkType.ELECT,new ElectWorker()); } public void doing(String command){ scheduler.get(ANALYSIS_WORK_TYPE.apply(command)).doingJob(command); } /** * 分析命令的任务类型 */ static final Function<String,String> ANALYSIS_WORK_TYPE = command->{ if(command.contains(WorkType.WOOD)){ return WorkType.WOOD; }else if(command.contains(WorkType.ELECT)){ return WorkType.ELECT; } throw new UnsupportedOperationException(); }; interface WorkType{ String WOOD = "Wood"; String ELECT = "Elect"; } }
经理管理了工人,通过scheduler
进行任务调度,他不是命令/任务的最终执行者,他会根据命令分析具体的任务类型,再安排具体的工人去干活。
管理经理的当然是老板,老板只是需要发号施令给经理,不需要知道任务具体是谁去执行。
public class Boss { public void command(String command,Manager manager){ manager.doing(command); } }
执行流程。
public class DelegatingApp { public static void main(String[] args) { new Boss().command("anybody Wood",new Manager()); new Boss().command("anybody Elect",new Manager()); } }
执行后输出。
整个程序UML类图如下
三、总结
总的来说,使用委托模式,会让逻辑层次更加分明,各个角色的职责划分更加清晰,代码实现上也会优雅不少。但同时也要注意区分一下代理模式、委派模式、策略模式三者的区别。