《架構模式應用 ● 設計模式》之命令者

/**************************************************************************************************
** 設計思想需要歸納與提煉,無論簡單抑或複雜。當然方案未必是唯一的最佳路徑,在總結
** 的過程中發現問題、改善問題;只有跳出業務,將複雜問題簡單化,才能提綱挈領,尋找
** 共性與變化的制高點!
************************************************************************************************/

   

§案例場景:

1、服務系統負責接收外部調用請求,考慮性能問題,將此請求轉發爲異步方式執行。

     即: 通過MQ將原始請求發送至後臺消息處理服務,完成業務邏輯異步Processing。

2、消息處理過程中,存在異常失敗情況,需要進行二級隊列Process

3、另外考慮到消息的完整性、一致性,需要通過事務來控制消息處理。

§分析設計:

       通過命令方式,將消息的發送者、接受者、調用者分別委派到場景中的各實例對象,各部分單一職責的方式來處理,另外對於併發的消息命令、特殊命令,可以指定不同的Receiver,處理不同的業務Path.

§設計實現:

1、 設計類圖

 


MessageReceiver 執行消息處理操作(Receiver)

MessageCommand 消息命令(可將命令與消息分開)

IMessageInvoker 調用消息的處理方法(Invoker)

ThreadClient 創建消息並綁定消息調用者

2、 代碼實現

     //ThreadClient.cs
    /// <summary>
    /// 創建消息並綁定消息調用者
    /// </summary>
    public class ThreadClient
    {
        public static List<Thread> _threadArray = new List<Thread>();

        /// <summary>
        /// 隊列參數設置
        /// </summary>
        public QueueSettings QueueSettings
        {
            get;
            set;
        }

        public Thread Initialize(QueueSettings setting)
        {
            QueueSettings = setting;
            Thread thread = new Thread(new ThreadStart(this.Start));
            return thread;
        }

        /// <summary>
        /// 啓動接收消息線程
        /// </summary>
        public void Start()
        {
            MessageReceiver receiver = new MessageReceiver(QueueSettings);
            Command command = new MessageCommand(receiver);
            IMessageInvoker invoker = new IMessageInvoker();

            invoker.SetCommand(command);
            invoker.ExecuteCommand();
        }
    }

IMessageInvoker.cs

    /// <summary>
    /// 調用消息的處理方法
    /// </summary>
    public class IMessageInvoker
    {
        private Command command;

        public void SetCommand(Command command)
        {
            this.command = command;
        }

        public void ExecuteCommand()
        {
            command.Execute();
        }
    }
MessageReceiver.cs

/// <summary>
    /// 執行消息處理操作
    /// </summary>
    public class MessageReceiver
    {
        /// <summary>
        /// 隊列參數設置
        /// </summary>
        public QueueSettings QueueSettings
        {
            get;
            set;
        }

        private DepositOrderInfo _depositInfo = null;

        public MessageReceiver(QueueSettings setting)
        {
            QueueSettings = setting;
        }

        public int Process(object data)
        {
            #region 驗證基本參數
            #endregion

            #region 填充訂單明細
            #endregion

            #region 保存訂單
            #endregion

            return Consts.Success;
        }
    }

MessageCommand.cs

    /// <summary>
    /// 消息命令
    /// </summary>
    public class MessageCommand : Command
    {
        MessageReceiver _receiver;
        string queuePath = string.Empty;

        public MessageCommand(MessageReceiver receiver) :
            base(receiver)
        {
            _receiver = receiver;
        }

        /// <summary>
        /// 處理消息
        /// </summary>
        public override void Execute()
        {
            QueueSettings = _receiver.QueueSettings;
            while (true)
            {
                try
                {
                    queuePath = QueueHelper.GetQueuePath(QueueSettings.QueueLevel);
                    if (!String.IsNullOrEmpty(queuePath) && SDMSMQ.GetAllMessageCount(queuePath) > 0)
                    {
                        //接收事務型消息

                        //Process
                    }

                    Thread.Sleep(QueueSettings.Interval);
                }
                catch (Exception ex)
                {
                    #region 發送到二級隊列
                    #endregion

                    #region 發送到監控系統
                    #endregion
                }
            }
        }
    }
Command.cs

    /// <summary>
    /// 各類消息命令基類
    /// </summary>
    public abstract class Command
    {
        protected MessageReceiver receiver;

        protected QueueSettings QueueSettings;

        public Command(MessageReceiver receiver)
        {
            this.receiver = receiver;
        }

        public abstract void Execute();
    }

調用示例

            public static List<Thread> _threadArray = new List<Thread>();

           //一級隊列線程
            Thread thread1 = new ThreadClient().Initialize(new QueueSettings { QueueLevel = QueueLevel.First, 
                Interval = Configs.GetConfig<int>("Queue1Interval") });
            thread1.Start();
            _threadArray.Add(thread1);


§總結:

    當然,通過指定不同的命令,Process不同的消息未必要通過命令者,靈活應用其他類型模式也可以完成此過程。本例主要針對命令者給出Demo。

   另外上述接受者構造器中入參QueueSettings,很多時候可作爲命令中介適配器:

    public class CommandAdapterInfo
    {
        List<CommandAdapterInfo> CommandList = null;

        public CommandAdapterInfo Create()
        {
            Init();

            return this.CommandList.Find(delegate(CommandAdapterInfo _adapter)
            {
                return _adapter.CommandType == this.CommandType;
            });
        }

        void Init()
        {
            this.CommandList = new List<CommandAdapterInfo>();

            //提現
            CommandAdapterInfo adapter = new CommandAdapterInfo();
            adapter.CommandType = CommanderType.Commission;
            adapter.Receiver = new CommissionMessageReceiver(adapter);
            adapter.Command = new CommissionMessageCommand(adapter.Receiver);
            adapter.Invoker = new CommissionMessageInvoker();
            this.CommandList.Add(adapter);

            //委託付款到卡
            CommandAdapterInfo adapterPayToCard = new CommandAdapterInfo();
            adapterPayToCard.CommandType = CommanderType.PayToCard;
            adapterPayToCard.Receiver = new CommissionMessageReceiver(adapterPayToCard);
            adapterPayToCard.Command = new CommissionMessageCommand(adapterPayToCard.Receiver);
            adapterPayToCard.Invoker = new CommissionMessageInvoker();
            this.CommandList.Add(adapterPayToCard);
            
        }

        /// <summary>
        /// 命令類型
        /// </summary>
        public CommanderType CommandType
        {
            get;
            set;
        }

        /// <summary>
        /// 命令接收者
        /// </summary>
        public MessageReceiver Receiver
        {
            get;
            set;
        }

        /// <summary>
        /// 命令執行
        /// </summary>
        public Command Command
        {
            get;
            set;
        }

        /// <summary>
        /// 調用者
        /// </summary>
        public MessageInvoker Invoker
        {
            get;
            set;
        }
    }

 


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章