以前接手過一個車輛監控的工具,接受第三方推送過來的車輛狀態數據而後入庫。車輛狀態一共有8種之多,每種狀態都須要作不一樣 處理操做。剛接手這份代碼時,針對此到處理,是龐大的if-else結構,if-else分支一多,分支內部邏輯再一複雜,到時候有多坑爹,我想接觸過的人必定知道。說代碼是藝術,這話對,但如今不想談藝術,只是這代碼看着fuck,怎能不優化。以前學習過設計模式,看到代碼時馬上就想到了責任鏈模式,因而開幹。至於具體責任鏈模式比較簡單,各位道行也比較深,很少說。json
一、定義抽象基處理器:設計模式
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)這二個虛方法實現各具體處理器中公共的處理邏輯。具體來講,針對第三方推送過來的原始報文,咱們須要保留一份,這個是針對全部狀態的,因此就放在這裏。ide
public void Handle(CarMessage carMessage)的做用相似模板方法模式中的那個模板方法,具體邏輯就是,若是當前消息類別(或者叫車輛狀態)等於本身應該處理的類別,則本身處理,若是不能處理或不該該處理,則調用鏈中下一個處理器。
二、各具體狀態對應的處理器
實際業務中, 第三方推送過來的狀態有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 }
看到沒,各責任方各自的邏輯都不一樣,並且各自只須要關心本身的責任(須要處理的業務邏輯)。性能
三、責任鏈的構造及調用學習
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);
四、注意點優化
1)並非具體業務對應多少狀態,咱們就須要有多少個處理器(責任方),例如本例中,雖然第三方推送過來8種狀態,但假設停車和熄火都只須要記錄消息報文,進入1千米才須要有特定的業務邏輯,那麼停車和熄火這兩種狀態能夠只定義一個處理器ui
2)關於責任鏈的構建,鑑於責任鏈上處理器的數目可能會比較多,若是每次收到消息都從新構建責任鏈再處理消息,太耗性能了,推薦構建一個責任鏈,處理全部消息this