使用责任链模式消除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
一.责任链模式的介绍 责任链模式用简单点的话来说,将责任一步一步传下去,这就是责任,想到这个我们可以相当击鼓传花,这个是为了方便记忆,另外就是我们在项目中经常用到的审批流程等这一类的场景时我们就可以考 ...
随机推荐
- R语言︱缺失值处理
#缺失值 an=c(1,2,NA) is.na(an) #会形成一个布尔向量 布尔向量就是一群像(FALSE,FALSE,TURE)这样的向量. 关于缺失值还有一个函数:complete.cases函 ...
- FusionCharts报错收录
FusionCharts报错 1.错误一 DesignTimeError:#25081843 flash-chart render Error >>#25081843:IECompatib ...
- 错误代码: 1305 PROCEDURE world.insert_data does not exist
1.错误描述 1 queries executed, 0 success, 1 errors, 0 warnings 查询:call insert_data() 错误代码: 1305 PROCEDUR ...
- Java中常见的Exception种类
Java中常见的Exception种类 1.ClassNotFoundException 2.IOException 3.NoSuchFieldException 4.NoSuchMethodExce ...
- Caused by: Unable to locate parent package [json-default] for [class com.you.user.action.StudentActi
1.错误描述 信息: Choosing bean (struts) for (com.opensymphony.xwork2.util.TextParser) 2014-7-13 1:52:04 or ...
- 芝麻HTTP:Python爬虫入门之Urllib库的基本使用
1.分分钟扒一个网页下来 怎样扒网页呢?其实就是根据URL来获取它的网页信息,虽然我们在浏览器中看到的是一幅幅优美的画面,但是其实是由浏览器解释才呈现出来的,实质它是一段HTML代码,加 JS.CSS ...
- table问题汇总
平时要使用 table 的次数说多不多,说少不少,但每次使用必定会被几个问题"坑"一下,所以这篇博客用来记录下table那些"小坑".但 table 也会有很多 ...
- 又把JDK改回JDK1.8的过程
我已经在崩溃的边缘. 先在控制面板卸载9.0.4,非常好,卸的干干净净的. 然后继续卸载9.0.1,也很好,卸的很干净. 命令行: 安装JDK1.8 装完了,去配环境变量: 4个环境变量都配齐了. J ...
- 【BZOJ4869】相逢是问候(线段树,欧拉定理)
[BZOJ4869]相逢是问候(线段树,欧拉定理) 题面 BZOJ 题解 根据欧拉定理递归计算(类似上帝与集合的正确用法) 所以我们可以用线段树维护区间最少的被更新的多少次 如果超过了\(\varph ...
- 【洛谷1855】 榨取kkksc03
题面 前面省去一堆背景内容 洛谷的运营组决定,如果一名oier向他的教练推荐洛谷,并能够成功的使用(成功使用的定义是:该团队有20个或以上的成员,上传10道以上的私有题目,布置过一次作业并成功举办过一 ...
