使用責任鏈模式消除if分支實踐

以前接手過一個車輛監控的工具,接受第三方推送過來的車輛狀態數據而後入庫。車輛狀態一共有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

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息