海水正藍

          面朝大海,春暖花開
          posts - 145, comments - 29, trackbacks - 0, articles - 1
            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

          【轉】-命令模式

          Posted on 2012-07-11 21:54 小胡子 閱讀(160) 評論(0)  編輯  收藏

          1. 概述

            將一個請求封裝為一個對象,從而使你可用不同的請求對客戶進行參數化; 對請求排隊或記錄請求日志,以及支持可撤銷的操作。

          2. 解決的問題

            在軟件系統中,行為請求者與行為實現者通常是一種緊耦合的關系,但某些場合,比如需要對行為進行記錄、撤銷或重做、事務等處理時,這種無法抵御變化的緊耦合的設計就不太合適。

          3. 模式中角色

            3.1 抽象命令(Command):定義命令的接口,聲明執行的方法。

            3.2 具體命令(ConcreteCommand):具體命令,實現要執行的方法,它通常是“虛”的實現;通常會有接收者,并調用接收者的功能來完成命令要執行的操作。

            3.3 接收者(Receiver):真正執行命令的對象。任何類都可能成為一個接收者,只要能實現命令要求實現的相應功能。

            3.4 調用者(Invoker):要求命令對象執行請求,通常會持有命令對象,可以持有很多的命令對象。這個是客戶端真正觸發命令并要求命令執行相應操作的地方,也就是說相當于使用命令對象的入口。

            3.5 客戶端(Client):命令由客戶端來創建,并設置命令的接收者。

          4. 模式解讀

            4.1 命令模式的類圖

            

            4.2 命令模式的實現代碼


          /// <summary>
              /// 接收者類,知道如何實施與執行一個請求相關的操作,任何類都可能作為一個接收者。
              /// </summary>
              public class Receiver
              {
                  
          /// <summary>
                  /// 真正的命令實現
                  /// </summary>
                  public void Action()
                  {
                      Console.WriteLine(
          "Execute request!");
                  }
              }

              
          /// <summary>
              /// 抽象命令類,用來聲明執行操作的接口
              /// </summary>
              public interface ICommand
              {
                  
          void Execute();
              }

              
          /// <summary>
              /// 具體命令類,實現具體命令。
              /// </summary>
              public class ConcereteCommand : ICommand
              {
                  
          // 具體命令類包含有一個接收者,將這個接收者對象綁定于一個動作
                  private Receiver receiver;

                  
          public ConcereteCommand(Receiver receiver)
                  {
                      
          this.receiver = receiver;
                  }

                  
          /// <summary>
                  /// 說這個實現是“虛”的,因為它是通過調用接收者相應的操作來實現Execute的
                  /// </summary>
                  public void Execute()
                  {
                      receiver.Action();
                  }
              }

              
          /// <summary>
              /// 調度類,要求該命令執行這個請求
              /// </summary>
              public class Invoker
              {
                  
          private ICommand command;

                  
          /// <summary>
                  /// 設置命令
                  /// </summary>
                  /// <param name="command"></param>
                  public void SetCommand(ICommand command)
                  {
                      
          this.command = command;
                  }

                  
          /// <summary>
                  /// 執行命令
                  /// </summary>
                  public void ExecuteCommand()
                  {
                      command.Execute();
                  }
              }
          4.3 客戶端代碼

          class Program
              {
                  
          static void Main(string[] args)
                  {
                      Receiver receiver 
          = new Receiver();
                      ICommand command 
          = new ConcereteCommand(receiver);
                      Invoker invoker 
          = new Invoker();

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

                      Console.Read();
                  }
              }
          執行結果

            

            4.4 模式分析

              4.4.1 本質:對命令進行封裝,將發出命令與執行命令的責任分開。

              4.4.2 每一個命令都是一個操作:請求的一方發出請求,要求執行一個操作;接收的一方收到請求,并執行操作。

              4.4.3 請求方和接收方獨立開來,使得請求的一方不必知道接收請求的一方的接口,更不必知道請求是怎么被接收,以及操作是否被執行、何時被執行,以及是怎么被執行的。

              4.4.4 使請求本身成為一個對象,這個對象和其它對象一樣可以被存儲和傳遞。

              4.4.5 命令模式的關鍵在于引入了抽象命令接口,且發送者針對抽象命令接口編程,只有實現了抽象命令接口的具體命令才能與接收者相關聯。 

          5. 模式總結

            5.1 優點

              5.1.1 解除了請求者與實現者之間的耦合,降低了系統的耦合度。

              5.1.2 對請求排隊或記錄請求日志,支持撤銷操作。

              5.1.3 可以容易地設計一個組合命令。

              5.1.4 新命令可以容易地加入到系統中。

            5.2 缺點

              5.2.1 因為針對每一個命令都需要設計一個具體命令類,使用命令模式可能會導致系統有過多的具體命令類。

            5.3 適用場景

              5.3.1 當需要對行為進行“記錄、撤銷/重做”等處理時。

              5.3.2 系統需要將請求者和接收者解耦,使得調用者和接收者不直接交互。

              5.3.3 系統需要在不同時間指定請求、請求排隊和執行請求。

              5.3.4 系統需要將一組操作組合在一起,即支持宏命令。

          6. 應用舉例:銀行帳號的存款、提款

            6.1 類圖

            

            6.2 代碼實現


          /// <summary>
              /// 銀行帳號
              /// </summary>
              public class Account
              {
                  
          /// <summary>
                  /// 帳號總金額
                  /// </summary>
                  private decimal totalAmount { get; set; }

                  
          /// <summary>
                  /// 存錢
                  /// </summary>
                  /// <param name="amount"></param>
                  public void MoneyIn(decimal amount)
                  {
                      
          this.totalAmount += amount;
                  }

                  
          /// <summary>
                  /// 取錢
                  /// </summary>
                  /// <param name="amount"></param>
                  public void MoneyOut(decimal amount)
                  {
                      
          this.totalAmount -= amount;
                  }

                  
          public decimal GetTotalAmout()
                  {
                      
          return totalAmount;
                  }
              }

              
          public abstract class Command
              {
                  
          protected Account account;

                  
          public Command(Account account)
                  {
                      
          this.account = account;
                  }

                  
          public abstract void Execute();
              }

              
          /// <summary>
              /// 存款命令
              /// </summary>
              public class MoneyInCommand : Command
              {
                  
          private decimal amount;

                  
          public MoneyInCommand(Account account, decimal amount)
                      : base(account)
                  {
                      
          this.amount = amount;
                  }

                  
          /// <summary>
                  /// 實現存錢命令
                  /// </summary>
                  public override void Execute()
                  {
                      account.MoneyIn(amount);
                  }
              }

              
          /// <summary>
              /// 取款命令類
              /// </summary>
              public class MoneyOutCommand : Command
              {
                  
          private decimal amount;
                  
          public MoneyOutCommand(Account account, decimal amount)
                      : base(account)
                  {
                      
          this.amount = amount;
                  }

                  
          /// <summary>
                  /// 實現取錢命令
                  /// </summary>
                  public override void Execute()
                  {
                      account.MoneyOut(amount);
                  }
              }

              
          public class Invoker
              {
                  
          private Command command;

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

                  
          public void ExecuteCommand()
                  {
                      command.Execute();
                  }
              }
          6.3 客戶端代碼

          class Program
              {
                  
          static void Main(string[] args)
                  {
                      
          // 創建銀行帳號
                      Account account = new Account();
                      
          // 創建一個存入500元的命令
                      Command commandIn = new MoneyInCommand(account,500);
                      
          // 創建一個調度者
                      BankAccount.Invoker invoker = new BankAccount.Invoker();

                      
          // 設置存錢命令
                      invoker.SetCommand(commandIn);
                      
          // 執行
                      invoker.ExecuteCommand();
                      Console.WriteLine(
          "The current amount is " + account.GetTotalAmout().ToString("N2"));

                      
          // 再次存入500
                      Command commandIn2 = new MoneyInCommand(account, 500);
                      invoker.SetCommand(commandIn2);
                      invoker.ExecuteCommand();
                      Console.WriteLine(
          "The current amount is " + account.GetTotalAmout().ToString("N2"));

                      
          // 取出300
                      Command commandOut = new MoneyOutCommand(account, 300);
                      invoker.SetCommand(commandOut);
                      invoker.ExecuteCommand();
                      Console.WriteLine(
          "The current amount is " + account.GetTotalAmout().ToString("N2"));

                      Console.Read();
                  }
              }

           執行結果

            


          轉自:
          http://www.cnblogs.com/wangjq/archive/2012/07/11/2585930.html



          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 靖江市| 塔城市| 若羌县| 新野县| 交城县| 上思县| 宣恩县| 长兴县| 墨玉县| 罗平县| 芦溪县| 定日县| 盐山县| 霞浦县| 黄冈市| 大邑县| 微山县| 郴州市| 北碚区| 政和县| 嘉鱼县| 泊头市| 嘉义县| 万山特区| 喜德县| 将乐县| 镇安县| 改则县| 衡山县| 安达市| 凉山| 铜梁县| 镇沅| 祁东县| 兴海县| 梨树县| 留坝县| 胶南市| 安岳县| 海晏县| 高尔夫|