在线客服项目算是告一段落了,从结果来看是没有达到自己一开始设想,因为一开始想好的设计,没能完全去实现。于是在平衡反思和甩锅的心态后,抛出原因:能力有限,时间有限,关联的业务无限。
此外就是这次开发虽然是基于1.0版本的升级,但是上线的时候, 发现不仅没填上之前的坑,还挖了新坑(线上出现业务逻辑丢失以及没完全兼容已上线的衍生的功能),于是在上线之后的发布日进行优化修复。
在各种不足中,也还是有一些收获的,比如锁粒度的优化,分级锁的使用,会话的公平分配,注解校验接口参数,MySQL查询优化等等, 但是今天要聊的是在项目中使用的一种设计模式:委派者模式。
在很久之前自己也整理了23种设计模式(18年的时候写的,现在仍然放在公众号里面,好坏就不说了),但是在日常开发中,设计模式还是很少结合实际去运用, 自己熟悉且常用的设计模式无非就是单例,策略,代理这三种。23种设计模式分为创建型模式,结构型模式和行为型模式,我们要说的委派者模式并不在23种设计模式中,它的功能核心是任务的调用和分配任务, 这种模式中主要包含了三种角色: 抽象任务角色, 委派者角色, 具体任务角色。
我们熟知具体的应用: Spring MVC 中的 DispatcherServlet 根据 handlerMapping 转发具体执行逻辑到 Controller就是使用委派者模式
下面来谈一谈这种设计模式的使用。
在线客服系统中,有一些常规动作:转交,挂起,分配,关闭。这些名词,我想都不难理解,因为我们打10086的人工客服可能都会听过。这些动作对于服务端而言就是不同的请求,服务端开发人员会为每一种动作的请求开发接口,每个接口调用不同的方法来执行不同的操作,就像下面 这样,对于每一种请求去调用不同的方法:
public class Test{
@Autowired
private ChatService service;
@RequestMapping("close")
public void close(){
service.close();
}
@RequestMapping("distribute")
public void distribute(){
service.distribute();
}
}
但是这些动作需要使用的方法我们可以不需要去关注, 我们只需要知道需要的动作,具体谁去做,我们可以找到一个中间人(委派者,或者中介)让他去找相应的方法去执行就行。
那么如何设计?
第一步
我们首先对任务动作进行抽象:Execute接口。然后将具体的任务角色(执行的方法)进行实现, 比如负责转交的角色叫做Transfer,负责关闭的角色叫做Close,负责分配的角色叫做Distribute,他们都实现Execute接口。
public interface Execute {
void execute(GroupChatInfoDo groupChatInfoDo);
}
//分配
public class Distribute implements Execute {
@Override
public void execute(GroupChatInfoDo groupChatInfoDo) {
System.out.println("分配动作");
}
}
//转交
public class Transfer implements Execute {
@Override
public void execute(GroupChatInfoDo groupChatInfoDo) {
System.out.println("转交动作");
}
}
//关闭
public class Cloes implements Execute {
@Override
public void execute(GroupChatInfoDo groupChatInfoDo) {
System.out.println("关闭动作");
}
}
//挂起
public class HangUp implements Execute {
@Override
public void execute(GroupChatInfoDo groupChatInfoDo) {
System.out.println("挂起动作");
}
}
第二步:
将动作封装成枚举(也可以使用策略模式来避免委派者模式违背开闭原则)
public enum OperationEnum {
CLOSE(new Cloes()),//关闭
DISTRIBUTE(new Distribute()),//分配
TRANSFER(new Transfer()),//转交
HANGUP(new HangUp());//挂起
private Execute execute;
OperationEnum(Execute execute) {
this.execute = execute;
}
public Execute getExecute() {
return execute;
}
}
第三步:
设置委派者(中介)
public class Middleman {
public static void center(OperationEnum operationEnum, GroupChatInfoDo groupChatInfoDo) {
operationEnum.getExecute().execute(groupChatInfoDo);
}
}
调用
public class Test{
@Autowired
private Middleman middleman;
@RequestMapping("close")
public void close(){
middleman.center(OperationEnum.CLOSE);
}
@RequestMapping("distribute")
public void distribute(){
middleman.center(OperationEnum.DISTRIBUTE);
}
}
这样设计首先简化了方法的调用,其次就是对内隐藏功能的实现。