浅析责任链模式在视频审核场景中的应用
类间关系尽量使用聚合、组合来实现,如果不可以的话再使用继承。目的还是为了降低类间耦合度,类间关系有六种,它们的耦合度大小关系是:泛化>实现>组合>聚合>关联>依赖,我们在设计架构时,尽量让类间关系靠近右边(就是采用耦合度更小的关系)。
03
业务场景应用案例
一个视频文件从用户电脑到发布到网络上通常要经历,上传、转码、审核、发布四个阶段,本文描述的业务场景适用于视频的审核与发布阶段。不同来源的视频审核策略不同,不同时期的视频审核策略不同,不同级别用户生成的视频审核策略不同等等。视频在审核阶段需要根据不同的审核策略进行处理。
在业务发展的初期,没有采用设计模式来指导编写代码。针对不同的审核策略处理视频的业务代码伪码如下:
if (videoInfo.getUploadFrom().equals("狐友") || videoInfo.getUploadFrom().equals("新闻")) {
}else{
}
if (videoInfo.getUploadFrom().equals("特邀作者上传") || videoInfo.getUploadFrom().equals("抓取来源")) {
} else{
}
if (videoInfo.getUploadFrom().equals("广告不适") || videoInfo.getUploadFrom().equals("严肃")) {
} else{
}
if ("命中MD5黑名单") {
} else{
}
if (videoInfo.getUploadFrom().equals("普通视频")) {
} else{
}
if (videoInfo.getUploadFrom().equals("免审标签") || videoInfo.getUploadFrom().equals("免审产品") || videoInfo.getUploadFrom().equals("免审用户")) {
} else{
}
if (videoInfo.getUploadFrom().equals("适用图片检测")) {
} else{
}
if (videoInfo.getUploadFrom().equals("适用音频检测")) {
} else{
}
if (videoInfo.getUploadFrom().equals("适用文本检测")) {
} else{
}
if (videoInfo.getUploadFrom().equals("适用全部类型AI检测")) {
} else{
}
if (videoInfo.getUploadFrom().equals("适用风险预测")) {
} else{
}
if (videoInfo.getUploadFrom().equals("适用基因检测")) {
} else{
}
if (now().between(time1, time2)&& isSensitiveAreaIp()) {
} else{
}
if (videoInfo.getUploadFrom().equals("适用产品策略检测")) {
} else{
}
代码使用了大量的if else语句,且如果随着业务的发展需要增加新的处理逻辑则又要对源码添加if else语句,违反了开闭原则,使得代码的可扩展性非常差。如果if else中的逻辑比较复杂,常常会由于增加新的逻辑而引入bug。这种业务代码特别适合使用责任链模型进行重构。
责任链模式的本质是将请求与处理解耦,允许将请求沿着处理器链进行发送。收到请求后,每个处理器均可对请求进行处理,或将其传递给链上的下个处理器。当新增处理逻辑时,不会对请求逻辑造成影响,两者互不干扰。示例图如下:
04
初级实现
public interface Handler {
void handle(Object videoInfo);
void setNext(Handler handler);
}
然后构建三个具体的处理器实现类,实际工作中要对应原业务代码实现相应数量的处理器类,这里为了陈述方便,只实现三个处理器类。
public class Handler1 implements Handler {
private Handler next;
@Override
public void handle(Object videoInfo) {
System.out.println("handler1处理");
if (next != null) {
next.handle(videoInfo);
}
}
@Override
public void setNext(Handler handler) {
this.next = handler;
}
}
public class Handler2 implements Handler {
private Handler next;
@Override
public void handle(Object videoInfo) {
System.out.println("handler2处理");
if (next != null) {
next.handle(videoInfo);
}
}
@Override
public void setNext(Handler handler) {
this.next = handler;
}
}public class Handler3 implements Handler {
private Handler next;
@Override
public void handle(Object videoInfo) {
System.out.println("handler3处理");
if (next != null) {
next.handle(videoInfo);
}
}
@Override
public void setNext(Handler handler) {
this.next = handler;
}
}
public class Client {
public static void main(String[] args) {
Handler handler1 = new Handler1();
Handler handler2 = new Handler2();
Handler handler3 = new Handler3();
handler1.setNext(handler2);
handler2.setNext(handler3);
handler1.handle("videoInfo");
}
}
打印结果为:
handler1处理
handler2处理
handler3处理
05
进阶实现
public interface Handler {
void handle(Object videoInfo);
}
public class Handler1 implements Handler {
@Override
public void handle(Object videoInfo) {
if (videoInfo.toString().contains("handler1")) {
System.out.println("handler1处理");
}
}
}
public class Handler2 implements Handler {
private Handler next;
@Override
public void handle(Object videoInfo) {
System.out.println("handler2处理");
}
}
public class Handler3 implements Handler {
private Handler next;
@Override
public void handle(Object videoInfo) {
System.out.println("handler3处理");
}
}public class HandlerChain {
private List<Handler> list = new ArrayList<>();
public void add(Handler handler) {
this.list.add(handler);
}
public void handle(Object videoInfo) {
list.forEach(handler -> handler.handle(videoInfo));
}
}
public class Client {
public static void main(String[] args) {
Handler handler1 = new Handler1();
Handler handler2 = new Handler2();
Handler handler3 = new Handler3();
HandlerChain handlerChain = new HandlerChain();
handlerChain.add(handler1);
handlerChain.add(handler2);
handlerChain.add(handler3);
handlerChain.handle("videoInfo");
}
}
运行结果为:
handler2处理
handler3处理
06
最终实现
@Component
public class Handler1 implements Handler {
@Override
public void handle(Object videoInfo) {
if (videoInfo.toString().contains("handler1")) {
System.out.println("handler1处理");
}
}
}
@Component
public class HandlerChain {
@Autowired
private List<Handler> list;
public void handle(Object videoInfo) {
list.forEach(handler -> handler.handle(videoInfo));
}
}
@Component
public class Client {
@Autowired
private HandlerChain handlerChain;
public void handle(Object videoInfo) {
handlerChain.handle(videoInfo);
}
}
07
总结