ステップバイステップの研究ノート9、コマンド(コマンドモード)キャンプ.NETのデザインパターンについて

アウトライン

ソフトウェアシステム、「リクエスタ動作」と「行動の実装」で一般に「密結合」を提示 しかし、このような「記録、アンドゥ/リドゥ、トランザクション」および他の治療の行動に関してはいくつかのケースでは、そのような変更は、密結合が適切でない抵抗することはできません。この場合、どのように、「行動の実装者」デカップリング「要求者の行動」のだろうか?抽象オブジェクトのグループの挙動は、両者間の疎結合を達成することができます。これは、この記事のCommandパターンということです。

意図

したがって、要求の異なるパラメータを使用してクライアントを作る、オブジェクトに対する要求をカプセル化し、元に戻すことができ、要求キューまたはログ要求、および運用支援。[GOF "デザインモード"]

Structureチャート

<デザインパターン>コマンドモードの構造は次のとおりです。

ALT

図1コマンドモード構造

例の西遊記:皇帝猿王のバイオグラフィーの天国

コマンドモードが天国で猿王ハボック前に、新しい発明ではありません。その後、猿神と呼ば玉皇大帝Taibaijinxingコマンド:南地位を向き、ストレート(shuiliandong)への「ヴィーナスと言った:「私は西、風水皇帝の恩赦令をTaibaijinxingています、あなたの下限大、Baishouに罪を記録。 "「天皇は、コマンドTaibaijinxingを発行することで、クライアントのシステムであり、猿王が受信者である、判決は、コマンドの順序です。ビジネスの玉皇大帝のためには、猿の王に報告するコミュニティを依頼することです。天皇は、単純にかかわらず、コマンドは猿の王に伝えているかの、コマンドを発行します。責任を法令が渡さTaibaijinxingが、どのように法令猿王を実装するには、猿王は、法令自身のことを実行するときです。そうでない場合は、猿王寺で長い列。

次のようにこの設計シミュレーションシステムは、次のとおりです。

PicX00104.gif

ライフ例

あなたが別の要求を使用してクライアントをパラメータ化することができますので、コマンドモードでは、オブジェクトに対する要求をカプセル化します。ビル・ダイニングには、コマンドモードの一例であるとき。シングルポイントのウェイター顧客の受け入れは、それが法案パッケージに課金しました。オーダーのポイントは、調理のためにキューイングされます。「法案」は、使用するさまざまな顧客のものとすることができるメニュー、に依存しないことに注意してください、それは単一のプロジェクトの挿入の異なる点となります。

ALT

コマンドモード食事図オブジェクトの例を用いて図2

構造の図の例示的な実施形態:

起動、シャットダウン、電話などのモバイルオペレーティングシステムは、電話を切る、テキストメッセージを送信し、SMS機能を削除し、次のように、実際には、これはコマンドモードで、クラス構造図です。

画像

 

まずインタフェースICommand.csを作成します。

    public interface ICommand
    {
        /// <summary>
        /// 执行命令
        /// </summary>
        string Execute();
        /// <summary>
        /// 撤消命令
        /// </summary>
        string UnExecute();
    }

 

再创建SystemCommand.cs:

  public  class SystemCommand
    {
       public string StartUp()
       {
           return "手机开机";
       }
       public string ShutDown()
       {
           return "手机关机";
       }
       public string SendSMS()
       {
           return "发短信";
       }
       public string RemoveSMS()
       {
           return "删短信";
       }
       public string CallPhone()
       {
           return "打电话";
       }
       public string RingOff()
       {
           return "挂电话";
       }
    }

 

再创建MobileSystem.cs:

 public abstract class MobileSystem :ICommand
    {
        private SystemCommand mobileCommand;

        public SystemCommand MobileCommand
        {
            get 
            {
                return mobileCommand;
            }
            set 
            {
                mobileCommand = value;
            }
        }


        public MobileSystem(SystemCommand command)
        {
            this.mobileCommand = command;
        }


        #region ICommand 成员

        public abstract string Execute();

       public abstract string UnExecute();

        #endregion
    }

 

再创建StartUp.cs:

   public  class StartUp :MobileSystem
   {
       #region MobileSystem 成员

       public override string  Execute()
        {
            return MobileCommand.StartUp();
        }

        public override string UnExecute()
        {
            return MobileCommand.ShutDown();
        }

        #endregion
        public StartUp(SystemCommand command)
            : base(command)
        { }
    }

 

再创建Call.cs:

 public class Call : MobileSystem
    {
        #region MobileSystem 成员

        public override string Execute()
        {
            return MobileCommand.CallPhone();
        }

        public override string UnExecute()
        {
            return MobileCommand.RingOff();
        }

        #endregion
        public Call(SystemCommand command)
            : base(command)
        { }
    }

 

再创建SMS.cs:

    public class SMS : MobileSystem
    {
        #region MobileSystem 成员

        public override string Execute()
        {
            return MobileCommand.SendSMS();
        }

        public override string UnExecute()
        {
            return MobileCommand.RemoveSMS();
        }

        #endregion
        public SMS(SystemCommand command)
            : base(command)
        { }
    }

 

 

再创建MobileServer.cs:

  public class MobileServer : ICommand
    {
       private MobileSystem mobileSystem;

       public MobileServer(MobileSystem system)
       {
           this.mobileSystem = system;
       }

       public string Execute()
       {
         return  mobileSystem.Execute();
       }

       public string UnExecute()
       {
           return mobileSystem.UnExecute();
       }

    }

 

最后再调用:

 public partial class Run : Form
    {
        public Run()
        {
            InitializeComponent();
        }

        private void btnRun_Click(object sender, EventArgs e)
        {

            SystemCommand command = new SystemCommand();

            MobileServer server = new MobileServer(new StartUp(command));
            rtbResult.AppendText(server.Execute() + "\n");
            rtbResult.AppendText(server.UnExecute() + "\n");
            server = new MobileServer(new Call(command));
            rtbResult.AppendText(server.Execute() + "\n");
            rtbResult.AppendText(server.UnExecute() + "\n");
            server = new MobileServer(new SMS(command));
            rtbResult.AppendText(server.Execute() + "\n");
            rtbResult.AppendText(server.UnExecute() + "\n");

        }
    }

 

看结果:

画像

效果及实现要点

1.Command模式的根本目的在于将“行为请求者”与“行为实现者”解耦,在面向对象语言中,常见的实现手段是“将行为抽象为对象”。

2.实现Command接口的具体命令对象ConcreteCommand有时候根据需要可能会保存一些额外的状态信息。

3.通过使用Compmosite模式,可以将多个命令封装为一个“复合命令”MacroCommand。

4.Command模式与C#中的Delegate有些类似。但两者定义行为接口的规范有所区别:Command以面向对象中的“接口-实现”来定义行为接口规范,更严格,更符合抽象原则;Delegate以函数签名来定义行为接口规范,更灵活,但抽象能力比较弱。

5.使用Command模式会导致某些系统有过多的具体命令类。某些系统可能需要几十个,几百个甚至几千个具体命令类,这会使命令模式在这样的系统里变得不实际。

6.从活动序列上来说通常是这样的一个过程:客户端指定一个命令的接受者;客户端创建一个具体的命令对象,并且告知接受者;客户端通过调用者对象来执行具体命令;调用者对象在合适的时候发出命令的执行指令;具体命令对象调用命令接受者的方法来落实命令的执行。

7.Command模式从结构上说变化非常多,要点就是一个抽象命令接口。抽象命令接口包含两个含义,一是把方法提升到类的层次,二是使用统一的接口来执行命令。

8.有了前面说的这个前提,我们才可以在调用者角色中做很多事情。比如,延迟命令的执行、为执行的命令记录日志、撤销执行的命令等等。

9.在应用的过程中可以省略一些不重要的角色。比如,如果只有一个执行者或者执行的逻辑非常简单的话,可以把执行的逻辑合并到具体命令角色中;如果我们并不需要使用调用者来做额外的功能,仅仅是希望通过命令模式来解除客户端和接受者之间耦合的话可以省略调用者角色。

10.如果需要实现类似于宏命令的命令组可以使用组合模式来封装具体命令。

11. 如果需要实现undo操作,那么命令接受者通常也需要公开undo的接口。在应用中,undo操作往往不是调用一下undo方法这么简单,因为一个操作执行后所改变的环境往往是复杂的。

适用性

在下面的情况下应当考虑使用命令模式:

1.使用命令模式作为"CallBack"在面向对象系统中的替代。"CallBack"讲的便是先将一个函数登记上,然后在以后调用此函数。

2.需要在不同的时间指定请求、将请求排队。一个命令对象和原先的请求发出者可以有不同的生命期。换言之,原先的请求发出者可能已经不在了,而命令对象本身仍然是活动的。这时命令的接收者可以是在本地,也可以在网络的另外一个地址。命令对象可以在串形化之后传送到另外一台机器上去。

3.系统需要支持命令的撤消(undo)。命令对象可以把状态存储起来,等到客户端需要撤销命令所产生的效果时,可以调用undo()方法,把命令所产生的效果撤销掉。命令对象还可以提供redo()方法,以供客户端在需要时,再重新实施命令效果。

4.如果一个系统要将系统中所有的数据更新到日志里,以便在系统崩溃时,可以根据日志里读回所有的数据更新命令,重新调用Execute()方法一条一条执行这些命令,从而恢复系统在崩溃前所做的数据更新。

5.命令的发起人和命令的接收人有不同的生命周期。比如,下遗嘱的这种行为就是命令模式,一般来说遗嘱执行的时候命令的发起人已经死亡,命令是否得到有效的执行需要靠律师去做的。

オブジェクトのプロパティを持つコマンド6.希望。所望のコマンドは、キュー操作に格納することができる;例えば、保存することができるアンドゥコマンドを実装することが望ましいです。行動の取り消しはGUIでは非常に一般的である、ネットワーク操作のコマンドキューも非常に一般的です。

7.クラスアクションの私たちのクラスの拡張機能のレベルは、控えめに言っても、かなりの柔軟性となり上昇させるコマンドの後、我々はコマンドモードと組み合わせて使用​​されるいくつかの種類のモードと構造モデルを作成することができます。

概要

1.Commandモデルは、その基本的な目的は、「要求者の行動」することであり、「行動の実装者」デカップリングデザインパターンは非常にシンプルかつエレガントです。

2.あなたは言葉この文章を考えてみて理解できない場合は、複雑なコマンドモード構造は、混同しないで、「給付のクラスレベルのメソッドは、コマンドモードの利点はあります。」

3.とコマンドモードに比べ状態または戦略パターンモードのクラスに言及状態またはアルゴリズムのレベルは、それ以上のクラスまたはオブジェクトを生成することができます。

ます。https://www.cnblogs.com/springyangwc/archive/2011/04/13/2015456.htmlで再現

おすすめ

転載: blog.csdn.net/weixin_33920401/article/details/94228140