設計モード:コマンドモード(Command Pattern)
15471 ワード
作者:TerryLee創建于:2006-07-17出典:http://terrylee.cnblogs.com/archive/2006/07/17/Command_Pattern.html収録于:2013-02-28
概要
ソフトウェアシステムでは、動作要求者と動作実装者は、通常、「緊密な結合」を示す.しかし、場合によっては、動作を「記録、取り消し/やり直し、トランザクション」などの処理を行うなど、変化を防ぐことができない緊密な結合は適切ではありません.この場合、「動作リクエスト者」と「動作実装者」をどのようにデカップリングしますか?一組の行為を対象として抽象化し,両者の間の松結合[李建忠]を実現できる.これが本稿で言うCommandモードです.
構造図
意図
1つのリクエストをオブジェクトにカプセル化し、異なるリクエストで顧客をパラメータ化できます.リクエストに対してキューまたはログを記録し、取り消し可能な操作をサポートします.
適用性は、オブジェクト指向システムにおける「CallBack」の代替としてコマンドモードを使用する.「CallBack」は、まず1つの関数を登録し、後でこの関数を呼び出すことを意味します. は、異なる時間にリクエストを指定し、リクエストをキューに入れる必要がある.1つのコマンドオブジェクトと元のリクエスト発行者は、異なるライフサイクルを持つことができます.すなわち、元のリクエスト送信者はもういないかもしれないが、コマンドオブジェクト自体はまだアクティブである.この場合、コマンドの受信者は、ローカルであってもよいし、ネットワークの別のアドレスであってもよい.コマンドオブジェクトは、シリアル化後に別のマシンに転送できます. システムは、コマンドの取り消しをサポートする必要がある.コマンドオブジェクトは、クライアントがコマンドによる効果を取り消す必要がある場合にundo()メソッドを呼び出し、コマンドによる効果を取り消すことができます.コマンドオブジェクトは、クライアントが必要に応じてコマンド効果を再実施するためのredo()メソッドも提供することができる. システムがシステムのすべてのデータをログに更新する場合、システムがクラッシュしたときに、ログに基づいてすべてのデータ更新コマンドを読み返し、Execute()メソッドを1つずつ呼び出してこれらのコマンドを実行し、システムがクラッシュする前に行ったデータ更新を復元することができます.
インプリメンテーションコード
View Code
1.クライアントプログラムでは、DocumentのDisplay()、Undo()、Redo()コマンドに依存せず、これらのコマンドをCommandでカプセル化し、その1つの鍵は抽象的なCommandクラスであり、操作のインタフェースを定義している.また,本来この3つの命令は3つの方法にすぎないが,Commandモードによってそれらをクラスレベルに言及することは,実際にはオブジェクト向けの原則に反しているが,命令を分離する要求者と命令の実行者の問題を優雅に解決し,Commandモードを使用する際には,その使用タイミングを判断しなければならない.
2.上記のUndo/Redoは単純に概略的に実現されているだけで、このような効果を実現するには、コマンドオブジェクトに状態を設定する必要があり、コマンドオブジェクトによって状態を格納することができる.
効果と実現のポイント
1.Commandモードの根本的な目的は、「動作要求者」と「動作実装者」をデカップリングすることであり、オブジェクト向け言語では、一般的な実装手段は「動作をオブジェクトとして抽象化する」ことである.
2.Commandインタフェースを実装する特定のコマンドオブジェクトConcreteCommandは、必要に応じて追加のステータス情報を保存する場合があります.
3.Compmositeモードを使用することで、複数のコマンドを1つの「複合コマンド」MacroCommandにカプセル化できます.
4.CommandモードはC#のDelegateと似ています.しかし、両者の定義行為インタフェースの規範には違いがある:Commandはオブジェクト向けの「インタフェース-実装」で行為インタフェースの規範を定義し、より厳格で、抽象的な原則に合致する.Delegateは関数署名で動作インタフェース仕様を定義し,より柔軟であるが抽象能力は弱い.
5.コマンド・モードを使用すると、特定のコマンド・クラスが多すぎるシステムがあります.いくつかのシステムでは、数十個、数百個、数千個の具体的なコマンドクラスが必要になる可能性があります.これにより、コマンドモードはこのようなシステムでは現実的ではありません.
まとめ
Commandモードは非常に簡単で優雅な設計モードであり、その根本的な目的は「動作要求者」と「動作実現者」をデカップリングすることである.
概要
ソフトウェアシステムでは、動作要求者と動作実装者は、通常、「緊密な結合」を示す.しかし、場合によっては、動作を「記録、取り消し/やり直し、トランザクション」などの処理を行うなど、変化を防ぐことができない緊密な結合は適切ではありません.この場合、「動作リクエスト者」と「動作実装者」をどのようにデカップリングしますか?一組の行為を対象として抽象化し,両者の間の松結合[李建忠]を実現できる.これが本稿で言うCommandモードです.
構造図
意図
1つのリクエストをオブジェクトにカプセル化し、異なるリクエストで顧客をパラメータ化できます.リクエストに対してキューまたはログを記録し、取り消し可能な操作をサポートします.
適用性
インプリメンテーションコード
View Code
1 public class Document
2 {
3 //
4 public void Display()
5 {
6 Console.WriteLine("Display");
7 }
8 //
9 public void Undo()
10 {
11 Console.WriteLine("Undo");
12 }
13 //
14 public void Redo()
15 {
16 Console.WriteLine("Redo");
17 }
18 }
19 public abstract class DocumentCommand
20 {
21 Document _document;
22 public DocumentCommand(Document doc)
23 {
24 this._document = doc;
25 }
26 public abstract void Execute();
27 }
28 //
29 public class DisplayCommand : DocumentCommand
30 {
31 public DisplayCommand(Document doc) : base(doc)
32 { }
33 public override void Execute()
34 {
35 _document.Display();
36 }
37 }
38 //
39 public class UndoCommand : DocumentCommand
40 {
41 public UndoCommand(Document doc) : base(doc)
42 { }
43 public override void Execute()
44 {
45 _document.Undo();
46 }
47 }
48 //
49 public class RedoCommand : DocumentCommand
50 {
51 public RedoCommand(Document doc) : base(doc)
52 { }
53 public override void Execute()
54 {
55 _document.Redo();
56 }
57 }
58 // Invoker
59 public class DocumentInvoker
60 {
61 DocumentCommand _discmd;
62 DocumentCommand _undcmd;
63 DocumentCommand _redcmd;
64 public DocumentInvoker(DocumentCommand discmd, DocumentCommand undcmd, DocumentCommand redcmd)
65 {
66 this._discmd = discmd;
67 this._undcmd = undcmd;
68 this._redcmd = redcmd;
69 }
70 public void Display()
71 {
72 _discmd.Execute();
73 }
74 public void Undo()
75 {
76 _undcmd.Execute();
77 }
78 public void Redo()
79 {
80 _redcmd.Execute();
81 }
82 }
83 class Program
84 {
85 static void Main(string[] args)
86 {
87 Document doc = new Document();
88 DocumentCommand discmd = new DisplayCommand(doc);
89 DocumentCommand undcmd = new UndoCommand(doc);
90 DocumentCommand redcmd = new RedoCommand(doc);
91 DocumentInvoker invoker = new DocumentInvoker(discmd, undcmd, redcmd);
92 invoker.Display();
93 invoker.Undo();
94 invoker.Redo();
95 }
96 }
1.クライアントプログラムでは、DocumentのDisplay()、Undo()、Redo()コマンドに依存せず、これらのコマンドをCommandでカプセル化し、その1つの鍵は抽象的なCommandクラスであり、操作のインタフェースを定義している.また,本来この3つの命令は3つの方法にすぎないが,Commandモードによってそれらをクラスレベルに言及することは,実際にはオブジェクト向けの原則に反しているが,命令を分離する要求者と命令の実行者の問題を優雅に解決し,Commandモードを使用する際には,その使用タイミングを判断しなければならない.
2.上記のUndo/Redoは単純に概略的に実現されているだけで、このような効果を実現するには、コマンドオブジェクトに状態を設定する必要があり、コマンドオブジェクトによって状態を格納することができる.
効果と実現のポイント
1.Commandモードの根本的な目的は、「動作要求者」と「動作実装者」をデカップリングすることであり、オブジェクト向け言語では、一般的な実装手段は「動作をオブジェクトとして抽象化する」ことである.
2.Commandインタフェースを実装する特定のコマンドオブジェクトConcreteCommandは、必要に応じて追加のステータス情報を保存する場合があります.
3.Compmositeモードを使用することで、複数のコマンドを1つの「複合コマンド」MacroCommandにカプセル化できます.
4.CommandモードはC#のDelegateと似ています.しかし、両者の定義行為インタフェースの規範には違いがある:Commandはオブジェクト向けの「インタフェース-実装」で行為インタフェースの規範を定義し、より厳格で、抽象的な原則に合致する.Delegateは関数署名で動作インタフェース仕様を定義し,より柔軟であるが抽象能力は弱い.
5.コマンド・モードを使用すると、特定のコマンド・クラスが多すぎるシステムがあります.いくつかのシステムでは、数十個、数百個、数千個の具体的なコマンドクラスが必要になる可能性があります.これにより、コマンドモードはこのようなシステムでは現実的ではありません.
まとめ
Commandモードは非常に簡単で優雅な設計モードであり、その根本的な目的は「動作要求者」と「動作実現者」をデカップリングすることである.