使用责任链模式消除if分支实践
之前接手过一个车辆监控的工具,接受第三方推送过来的车辆状态数据然后入库。车辆状态一共有8种之多,每种状态都需要做不同 处理操作。刚接手这份代码时,针对此处处理,是庞大的if-else结构,if-else分支一多,分支内部逻辑再一复杂,到时候有多坑爹,我想接触过的人一定知道。说代码是艺术,这话对,但现在不想谈艺术,只是这代码看着fuck,怎能不优化。之前学习过设计模式,看到代码时立刻就想到了责任链模式,于是开干。至于具体责任链模式比较简单,各位道行也比较深,不多说。
1、定义抽象基处理器:
public abstract class BaseHandler
{
#region Private Fields private readonly VehicleStatus _vehicleStatus; private readonly BaseHandler _nextHandler; #endregion #region Protected Fields protected readonly CarStatusMsgTextBLL _statusMsgTextBLL = new CarStatusMsgTextBLL(); protected readonly CarStatusBLL _statusBLL = new CarStatusBLL(); #endregion #region Constructors public BaseHandler(VehicleStatus vehicleStatus, BaseHandler nextHandler)
{
_vehicleStatus = vehicleStatus;
_nextHandler = nextHandler;
} #endregion #region Protected Methods protected virtual void ExecuteHandle(CarMessage carMessage)
{
//不再记录CarStatusMsgText,数据量太大
//CarStatusMsgText msgText = new CarStatusMsgText
//{
// Sys_Guid = Guid.NewGuid().ToString("N").ToUpper(),
// CreateDate = DateTime.Now,
// MsgText = carMessage.MessageContent
//};
//_statusMsgTextBLL.AddCarStatusMsgText(msgText);
} #endregion #region Public Methods public void Handle(CarMessage carMessage)
{
if (carMessage.VehicleStatus == _vehicleStatus)
{
this.ExecuteHandle(carMessage);
}
else if (_nextHandler != null)
{
_nextHandler.Handle(carMessage);
}
else
{
throw new Exception("未识别的消息类型:" + carMessage.MessageContent);
}
} #endregion
}
其中protected virtual void ExecuteHandle(CarMessage carMessage)这二个虚方法实现各具体处理器中公共的处理逻辑。具体来说,针对第三方推送过来的原始报文,我们需要保留一份,这个是针对所有状态的,所以就放在这里。
public void Handle(CarMessage carMessage)的作用类似模板方法模式中的那个模板方法,具体逻辑就是,如果当前消息类别(或者叫车辆状态)等于自己应该处理的类别,则自己处理,如果不能处理或不应该处理,则调用链中下一个处理器。 2、各具体状态对应的处理器
实际业务中, 第三方推送过来的状态有8种,分别代表停车、熄火、进入目的地1公里以内、离开目的地1公里以外、超速、暴力行驶等等,如下截图:
这里以停车和进入1公里以内来示例责任链中的责任方实现
public class StoppedHandler : BaseHandler
{
#region Constructors public StoppedHandler(BaseHandler nextHandler)
: base(VehicleStatus.Stopped, nextHandler)
{ } #endregion #region Protected Methods protected override void ExecuteHandle(CarMessage carMessage)
{
base.ExecuteHandle(carMessage); CarStatus carStatus = JsonConvert.DeserializeObject<CarStatus>(carMessage.MessageContent);
carStatus.Sys_Guid = Guid.NewGuid().ToString("N").ToUpper();
carStatus.CreateDate = DateTime.Now; _statusBLL.AddCarStatus(carStatus);
} #endregion
}
public class EnterNearbyHandler : BaseHandler
{
#region Constructors public EnterNearbyHandler(BaseHandler nextHandler)
: base(VehicleStatus.EnterNearby, nextHandler)
{ } #endregion #region Protected Methods protected override void ExecuteHandle(CarMessage carMessage)
{
base.ExecuteHandle(carMessage); CarStatus carStatus = JsonConvert.DeserializeObject<CarStatus>(carMessage.MessageContent);
carStatus.Sys_Guid = Guid.NewGuid().ToString("N").ToUpper();
carStatus.CreateDate = DateTime.Now;
carStatus.ReqIds = carStatus.RequestId;
_statusBLL.AddCarStatus(carStatus); if (!string.IsNullOrWhiteSpace(carStatus.ReqIds)
&& carStatus.ReceiveTime.HasValue)
{
_statusBLL.UpdateSignInTime(carStatus.ReqIds, carStatus.MobileNumber, carStatus.ReceiveTime.Value);
_statusBLL.ExecuteQuQian(carStatus.ReqIds);
}
} #endregion
}
看到没,各责任方各自的逻辑都不同,而且各自只需要关心自己的责任(需要处理的业务逻辑)。
3、责任链的构造及调用
private readonly BaseHandler _carMessageHandler = new StoppedHandler(
new StalledHandler(
new ACCOnAndFullSpeedHandler(
new ViolentDrivingHandler(
new EnterNearbyHandler(
new ParkingTimeoutHandler(
new ParkingTimeoutImgHandler(
new LeaveNearbyHandler(null))))))));
CarMessage carMessage = new CarMessage
{
VehicleStatus = (VehicleStatus)Convert.ToInt32(jsonObj["msgType"]),
MessageContent = message.Text
}; _carMessageHandler.Handle(carMessage);
4、注意点
1)并不是具体业务对应多少状态,我们就需要有多少个处理器(责任方),例如本例中,虽然第三方推送过来8种状态,但假设停车和熄火都只需要记录消息报文,进入1公里才需要有特定的业务逻辑,那么停车和熄火这两种状态可以只定义一个处理器
2)关于责任链的构建,鉴于责任链上处理器的数目可能会比较多,如果每次收到消息都重新构建责任链再处理消息,太耗性能了,推荐构建一个责任链,处理所有消息
使用责任链模式消除if分支实践的更多相关文章
- JavaScript设计模式-20.责任链模式
<html> <head> <title>javascript高级语法20-责任链模式</title> </head> <body&g ...
- 读书笔记之 - javascript 设计模式 - 责任链模式
责任链模式可以用来消除请求的发送者和接收者之间的耦合.这是通过实现一个由隐式地对请求进行处理的对象组成的链而做到的.链中的每个对象可以处理请求,也可以将其传给下一个对象. 责任链的结构: 责任链由多个 ...
- 设计模式(13)--Chain of Responsibility(责任链模式)--行为型
作者QQ:1095737364 QQ群:123300273 欢迎加入! 1.模式定义: 责任链模式是一种对象的行为模式.在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一 ...
- Java设计模式(19)——行为模式之责任链模式(chain of responsibilitiy)
一.概述 概念 UML简图 角色 抽象处理器:定义处理请求的接口 具体处理器:接收到请求后可以选择处理,也可以选择发给下家处理(持有下家的引用) 当然这里必须指出,实际中纯的责任链模式很难寻找,一般是 ...
- php设计模式-责任链模式
责任链模式更像是一种简化多种场景下调用处理的一种设计模式,特别适合if-else分支判断很多的场景.比如是根据不同会员等级给予不同的优惠力度. 它的定义:对象的调用是由下家的应用连接起来的处理链.一直 ...
- 责任链模式Scala的7种实现
责任链模式是经典的GoF 23种设计模式之一,也许你已经了解这种模式.不管你是否熟悉,建议读者在阅读本文之前,不妨先思考下面三个问题: (1) 如何用多种风格迥异的编程范式来实现责任链模式? (2) ...
- 重学 Java 设计模式:实战责任链模式「模拟618电商大促期间,项目上线流程多级负责人审批场景」
作者:小傅哥 博客:https://bugstack.cn - 原创系列专题文章 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 场地和场景的重要性 射击
- Activiti工作流学习笔记(四)——工作流引擎中责任链模式的建立与应用原理
原创/朱季谦 本文需要一定责任链模式的基础,主要分成三部分讲解: 一.简单理解责任链模式概念 二.Activiti工作流里责任链模式的建立 三.Activiti工作流里责任链模式的应用 一.简单理解责 ...
- 23种设计模式--责任链模式-Chain of Responsibility Pattern
一.责任链模式的介绍 责任链模式用简单点的话来说,将责任一步一步传下去,这就是责任,想到这个我们可以相当击鼓传花,这个是为了方便记忆,另外就是我们在项目中经常用到的审批流程等这一类的场景时我们就可以考 ...
随机推荐
- FusionCharts MSBar3D图
1.静态页面 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> ...
- R语言︱ROC曲线——分类器的性能表现评价
笔者寄语:分类器算法最后都会有一个预测精度,而预测精度都会写一个混淆矩阵,所有的训练数据都会落入这个矩阵中,而对角线上的数字代表了预测正确的数目,即True Positive+True Nagetiv ...
- Struts2实现文件上传(二)
Struts2实现文件上传 文件上传页面 file.jsp: <%@ page language="java" import="java.util.*" ...
- LeetCode 542. 01 Matrix
输入:只包含0,1的矩阵 输出:元素1到达最近0的距离 算法思想:广度优先搜索. 元素为0为可达区域,元素为1为不可达区域,我们的目标是为了从可达区域不断地扩展至不可达区域,在扩展的过程中,也就计算出 ...
- JavaScript设计模式(7)-设配器模式
适配器模式 1. 作用: 协调两个不同的接口 2. 适用场景 适配器适用于客户期待的接口与现有 API 提供的接口不兼容这种场景.他只能用来协调语法上的差异问题.适配器所适配的两个方法执行的应该是类似 ...
- Keras官方中文文档:函数式模型API
\ 函数式模型接口 为什么叫"函数式模型",请查看"Keras新手指南"的相关部分 Keras的函数式模型为Model,即广义的拥有输入和输出的模型,我们使用M ...
- jquery 实现拖动文件上传加进度条
通过对文件的拖动实现文件的上传,主要用到的是HTML5的ondrop事件,上传内容通道FormData传输: //进度条 <div class="parent-dlg" &g ...
- THUWC2018滚粗记
THUWC2018滚粗记 前言 又是一篇滚粗记, 不过可能还要写过很多很多篇滚粗记, 才会有一篇不是滚粗记的东西啦 总而言之,我现在还是太菜了 还要过一大段时间我才会变强啦 Day -inf 联赛考完 ...
- 【UVA 11426】gcd之和 (改编)
题面 \(\sum_{i=1}^{n}\sum_{j=1}^m\gcd(i,j)\mod998244353\) \(n,m<=10^7\) Sol 简单的一道莫比乌斯反演题 \(原式=\sum_ ...
- java把集合数据写入txt文档
List<String> list= bs.findJson(); try { BufferedWriter bw = new BufferedWriter(new FileWriter( ...
