ソフトウェア開発システムでは、しばしば「リクエスタ法」との間の密接な結合が存在するれる「実装アプローチは。」これは、ソフトウェアの機能の拡張やメンテナンスを助長されていません。例えば、実施「元に戻す、やり直し、記録」と処理が非常に不便であるにしたいので、「依頼者とメソッドの分離する方法の実装方法は?」非常に重要になってきて、コマンドモードは、良い解決策になることができますこの問題。
実生活では、多くのそのような例がある、例えば、テレビのリモコン(コマンド送信者)テレビへのリモートコントロールボタン(特定のコマンド)(コマンド受信機)のほか、「ファンクションキー」を経由して、コンピュータのキーボードで。
コマンドモードの定義と特性
次のように定義されたコマンド(コマンド)モードは、次のとおり要求及び責任の実行を分離要求するので、オブジェクトの要求をカプセル化します。ストレージ、転送、リコール、および増加した管理のためのコマンドオブジェクトやすいので、コマンドオブジェクトとの間のような通信。
次のようにコマンド・モードの主な利点はあります。
(1)カップリングシステムを減らします。従ってリクエスタと受信者との間の完全な分離を達成すること、リクエスタと受信者の間には直接参照するので、同じリクエスタが異なる受信者、これに対応していてもよい、受信者は、異なるリクエスタに対して同じであってもよいです使用は、両者の間の良好な独立性を持っています。
(2)新しいコマンドが容易にシステムに追加することができます。新しい具象コマンドクラスのほかに、それは他のクラスには影響しませんので、デカップリング送信者と受信者尋ねる
開閉の」原則を満たすために、元のシステムのソースコード、クラスコード、さらには顧客を修正することなく、簡単に新しいコンクリートのコマンドクラスを追加します「要件。
(3)比較的容易であるコマンドキュー又はマクロコマンド(コマンドの組み合わせ)を設計することができます。
(4)離脱(元に戻す)回復要求と(やり直し)動作のために設計および実装を提供
不利な点は以下のとおりです。
いくつかのシステムでは、あまりにも多くの特定のコマンドクラスを持っている可能性があり、コマンドモードを使用します。受信者の要求の操作をコールするたびに特定のコマンドクラスを設計する必要がありますので、ので、いくつかのシステムでコマンドモードに影響を与えるであろう、具体的なコマンドクラスの大規模な量を提供する必要があるかもしれません。
コマンドモードのアーキテクチャと実装
システム動作に関連するコマンドを実装分離に関連付けられた発呼者に抽象化することができる、以下の構造を有します。
1.構造モデル
コマンドモードでは、次の主要な役割が含まれています。
- 抽象クラスの命令(コマンド)の役割:コマンドを実行するためのインタフェースを宣言し、抽象メソッド)が(実行コマンドを実行する必要があります。
- 特定のコマンドの役割(コンクリートコマンド)の役割は:実行する操作コマンドを完了するために、受信者を呼び出すことにより、レシーバオブジェクトと機能を持つ抽象クラスCommandクラスの具体的な実現、です。
- 実現/レシーバ(受信側)役割:関連する操作コマンド機能を実行するには、ビジネス・オブジェクトの誰特定のオーダーを実現することです。
- 呼び出し側/要求者(実行者)の役割:送信者の要求、それは通常、コマンドオブジェクトをたくさん持っている、そしてコマンドオブジェクトにアクセスすることで、関連する要求を実現するために、それは直接受信者にアクセスしません。
図1に示す構造。
図1、図のコマンドモード構造。
実現の2モード
コマンドモードのコードは次のとおりです。
package command;
public class CommandPattern
{
public static void main(String[] args)
{
Command cmd=new ConcreteCommand();
Invoker ir=new Invoker(cmd);
System.out.println("客户访问调用者的call()方法...");
ir.call();
}
}
//调用者
class Invoker
{
private Command command;
public Invoker(Command command)
{
this.command=command;
}
public void setCommand(Command command)
{
this.command=command;
}
public void call()
{
System.out.println("调用者执行命令command...");
command.execute();
}
}
//抽象命令
interface Command
{
public abstract void execute();
}
//具体命令
class ConcreteCommand implements Command
{
private Receiver receiver;
ConcreteCommand()
{
receiver=new Receiver();
}
public void execute()
{
receiver.action();
}
}
//接收者
class Receiver
{
public void action()
{
System.out.println("接收者的action()方法被调用...");
}
}
次のようにプログラムの動作結果は以下のとおりです。
カスタマー・アクセス呼び出し側の呼び出し()メソッドが... コマンドのコマンドを実行して、発信者は... 受信者のアクション()メソッドが呼び出されます...
コマンドモードの応用例
[例1]例としては、顧客がコマンドモードで朝食を食べにレストランに行く実現します。
分析:顧客は、顧客が、朝食に比べていくつかのウェイターに作るために、関連するシェフにウェイター顧客の要求を選択することができるなど、朝食のご飯ロール、米麺とワンタンを持つレストランに行くことを選択することができます。ここでのポイントは、同等の朝食「注文」、ウェイターは「発信元」、「受信機」のシェフと同等と同等であり、適切なコマンドモードで達成されます。
まず、抽象Commandクラス、抽象メソッドの料理(あるクラスの朝食(朝食)、)を定義、何をすべきかを説明し、その後、米ロール(ChangFen)、ラビオリクラス(HunTun)とフォークラスのようなサブクラスを定義します( HeFen)、クラスの朝食の料理()メソッドを実装して、特定のコマンドクラスですが、彼らは、コンクリートをしないように具体的には、しかし、シェフに行い、具体的なクラスのシェフの料理は、米のロール(ChangFenChef)、ラビオリの日食のシェフを(持っていますHunTunChef)とフォーのクック(HeFenChef)、それらは図コックの本実施例は、ディスプレイを調理するため(コマンドの受信者であるレンダリングをダウンロードするためにここに表示される)ので、調理各サブクラスはJFrameのように定義されますクラスは、最後に、クラスのウェイター(ウェイター)の定義は、それは、調理用クライアントの要求を受けて調理すると、コマンドを発行します。クラス付随アラカルト、図によるクライアントクラス2は、図1の構成図です。
レストラン構造図で朝食を食べて、図2のお客様
コードは以下の通りであります:
package command;
import javax.swing.*;
public class CookingCommand
{
public static void main(String[] args)
{
Breakfast food1=new ChangFen();
Breakfast food2=new HunTun();
Breakfast food3=new HeFen();
Waiter fwy=new Waiter();
fwy.setChangFen(food1);//设置肠粉菜单
fwy.setHunTun(food2); //设置河粉菜单
fwy.setHeFen(food3); //设置馄饨菜单
fwy.chooseChangFen(); //选择肠粉
fwy.chooseHeFen(); //选择河粉
fwy.chooseHunTun(); //选择馄饨
}
}
//调用者:服务员
class Waiter
{
private Breakfast changFen,hunTun,heFen;
public void setChangFen(Breakfast f)
{
changFen=f;
}
public void setHunTun(Breakfast f)
{
hunTun=f;
}
public void setHeFen(Breakfast f)
{
heFen=f;
}
public void chooseChangFen()
{
changFen.cooking();
}
public void chooseHunTun()
{
hunTun.cooking();
}
public void chooseHeFen()
{
heFen.cooking();
}
}
//抽象命令:早餐
interface Breakfast
{
public abstract void cooking();
}
//具体命令:肠粉
class ChangFen implements Breakfast
{
private ChangFenChef receiver;
ChangFen()
{
receiver=new ChangFenChef();
}
public void cooking()
{
receiver.cooking();
}
}
//具体命令:馄饨
class HunTun implements Breakfast
{
private HunTunChef receiver;
HunTun()
{
receiver=new HunTunChef();
}
public void cooking()
{
receiver.cooking();
}
}
//具体命令:河粉
class HeFen implements Breakfast
{
private HeFenChef receiver;
HeFen()
{
receiver=new HeFenChef();
}
public void cooking()
{
receiver.cooking();
}
}
//接收者:肠粉厨师
class ChangFenChef extends JFrame
{
private static final long serialVersionUID = 1L;
JLabel l=new JLabel();
ChangFenChef()
{
super("煮肠粉");
l.setIcon(new ImageIcon("src/command/ChangFen.jpg"));
this.add(l);
this.setLocation(30, 30);
this.pack();
this.setResizable(false);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void cooking()
{
this.setVisible(true);
}
}
//接收者:馄饨厨师
class HunTunChef extends JFrame
{
private static final long serialVersionUID=1L;
JLabel l=new JLabel();
HunTunChef()
{
super("煮馄饨");
l.setIcon(new ImageIcon("src/command/HunTun.jpg"));
this.add(l);
this.setLocation(350, 50);
this.pack();
this.setResizable(false);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void cooking()
{
this.setVisible(true);
}
}
//接收者:河粉厨师
class HeFenChef extends JFrame
{
private static final long serialVersionUID=1L;
JLabel l=new JLabel();
HeFenChef()
{
super("煮河粉");
l.setIcon(new ImageIcon("src/command/HeFen.jpg"));
this.add(l);
this.setLocation(200, 280);
this.pack();
this.setResizable(false);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void cooking()
{
this.setVisible(true);
}
}
シナリオのコマンドモード
コマンドモードでは、通常のシーンで使用されています。
- ときにシステムは、発信者は、発信者が直接対話し、受信しないように、受信要求、コマンドモードから分離する必要があることが必要です。
- システムがランダムな順序の要求を必要とするか、頻繁に追加またはコマンドを削除すると、コマンド・モードでは、これらの機能を実装するために、より便利です。
- システムは、一連の操作を実行する必要がある場合は、コマンドモードでは、この機能マクロを達成するように定義することができます。
- システムは元に戻すコマンド(元に戻す)と回復動作(やり直し)動作をサポートする必要がある場合、コマンドオブジェクトが達成されるメモモードを使用して、保存することができます。
拡張コマンドモード
ソフトウェア開発では、時々、コマンドモードの前に、また、複合コマンドモードと呼ばれるマクロモードを構成する組み合わせて使用モードの組み合わせを、学びます。マクロコマンドのセットを含むコマンド、それは二重の役割と、発信者の特定のコマンドとして作用する、それが実行され、すべてのコマンドが含まれていることを再帰呼び出し、その具体的な構造は図3に示されています。
図3は、コマンドモードの組み合わせの構成図です。
コードは以下の通りであります:
package command;
import java.util.ArrayList;
public class CompositeCommandPattern
{
public static void main(String[] args)
{
AbstractCommand cmd1=new ConcreteCommand1();
AbstractCommand cmd2=new ConcreteCommand2();
CompositeInvoker ir=new CompositeInvoker();
ir.add(cmd1);
ir.add(cmd2);
System.out.println("客户访问调用者的execute()方法...");
ir.execute();
}
}
//抽象命令
interface AbstractCommand
{
public abstract void execute();
}
//树叶构件: 具体命令1
class ConcreteCommand1 implements AbstractCommand
{
private CompositeReceiver receiver;
ConcreteCommand1()
{
receiver=new CompositeReceiver();
}
public void execute()
{
receiver.action1();
}
}
//树叶构件: 具体命令2
class ConcreteCommand2 implements AbstractCommand
{
private CompositeReceiver receiver;
ConcreteCommand2()
{
receiver=new CompositeReceiver();
}
public void execute()
{
receiver.action2();
}
}
//树枝构件: 调用者
class CompositeInvoker implements AbstractCommand
{
private ArrayList<AbstractCommand> children = new ArrayList<AbstractCommand>();
public void add(AbstractCommand c)
{
children.add(c);
}
public void remove(AbstractCommand c)
{
children.remove(c);
}
public AbstractCommand getChild(int i)
{
return children.get(i);
}
public void execute()
{
for(Object obj:children)
{
((AbstractCommand)obj).execute();
}
}
}
//接收者
class CompositeReceiver
{
public void action1()
{
System.out.println("接收者的action1()方法被调用...");
}
public void action2()
{
System.out.println("接收者的action2()方法被调用...");
}
}
次のようにプログラムの動作結果は以下のとおりです。
カスタマー・アクセスは、発信者のexecute()メソッド... 受信者アクション1()メソッドが呼び出される... 受信者のアクション2()メソッドが呼び出されます...
それは後述する取消コマンドモード、となるように当然のことながら、同じメモは、組み合わせて使用するモード(メメント)モードを命令することができます。