コマンドモード


コマンド パターンはデータ駆動型の設計パターンであり、動作パターンです。リクエストはコマンド形式のオブジェクトにラップされ、呼び出し元のオブジェクトに渡されます。呼び出し元のオブジェクトは、コマンドを処理できる適切なオブジェクトを探し、対応するオブジェクトにコマンドを渡し、そこでコマンドが実行されます。


概要

目的: リクエストをオブジェクトにカプセル化し、さまざまなリクエストでクライアントをパラメータ化できるようにします。

主な解決策: ソフトウェア システムでは、動作要求者と動作実装者は通常、密結合した関係を持ちますが、場合によっては、動作の記録、元に戻す、またはやり直し、トランザクションなどが必要になる場合もあります。この種の密結合変化に耐えられないデザインは不向きです。

いつ使用するか: 「記録、元に戻す/やり直し、トランザクション」やその他の動作の処理などの状況によっては、変更に抵抗できないこの種の密結合は不適切です。この場合、「動作要求者」を「動作実装者」から切り離すにはどうすればよいでしょうか?一連の動作をオブジェクトに抽象化すると、それらの間の疎結合を実現できます。

解決方法: 発信者を通じて受信者を呼び出してコマンドを実行します。順序は発信者→受信者→コマンドです。

キーコード: 3つの役割を定義: 1. 受信した実際のコマンド実行オブジェクト 2. コマンド 3. 呼び出し者はコマンドオブジェクトの入口を使用します

応用例: struts 1 にはアクションコアコントローラー ActionServlet が 1 つだけあります。これは Invoker に相当し、モデル層クラスにはさまざまなアプリケーションを持つさまざまなモデル クラスがあり、特定のコマンドに相当します。

利点: 1. システムの結合を軽減します。 2. 新しいコマンドをシステムに簡単に追加できます。

欠点: コマンドモードを使用すると、一部のシステムで特定のコマンドクラスが多すぎる可能性があります。

使用シナリオ: コマンド モードは、次のようなコマンドが考慮されるあらゆる場所で使用できます。 1. GUI のすべてのボタンはコマンドです。 2. CMD をシミュレートします。

注: システムはコマンドの元に戻す (Undo) 操作と回復 (Redo) 操作をサポートする必要があります。 コマンド モードの拡張を参照してください。

実装

まずコマンドとしてインターフェイスOrderを作成し、次にリクエストとしてStockクラスを作成します。エンティティ コマンド クラス BuyStock および SellStockOrder インターフェイスを実装し、実際のコマンド処理を実行します。呼び出しオブジェクトとしてクラス Broker を作成します。このクラスは、注文を受け入れ、注文を行うことができます。

ブローカー オブジェクトはコマンド パターンを使用して、コマンドの種類に基づいてどのオブジェクトがどのコマンドを実行するかを決定します。 CommandPatternDemo のデモ クラスは、Broker クラスを使用してコマンド パターンを示します。

command_pattern_uml_diagram.jpg

ステップ 1

コマンドインターフェイスを作成します。

Order.java

public interface Order {
   void execute();
}

ステップ 2

リクエストクラスを作成します。

Stock.java

public class Stock {
	
   private String name = "ABC";
   private int quantity = 10;

   public void buy(){
      System.out.println("Stock [ Name: "+name+", 
         Quantity: " + quantity +" ] bought");
   }
   public void sell(){
      System.out.println("Stock [ Name: "+name+", 
         Quantity: " + quantity +" ] sold");
   }
}

ステップ 3

Order インターフェースを実装するエンティティ クラスを作成します。

BuyStock.java

public class BuyStock implements Order {
   private Stock abcStock;

   public BuyStock(Stock abcStock){
      this.abcStock = abcStock;
   }

   public void execute() {
      abcStock.buy();
   }
}

SellStock.java

public class SellStock implements Order {
   private Stock abcStock;

   public SellStock(Stock abcStock){
      this.abcStock = abcStock;
   }

   public void execute() {
      abcStock.sell();
   }
}

ステップ 4

コマンド呼び出しクラスを作成します。

Broker.java

import java.util.ArrayList;
import java.util.List;

   public class Broker {
   private List<Order> orderList = new ArrayList<Order>(); 

   public void takeOrder(Order order){
      orderList.add(order);		
   }

   public void placeOrders(){
      for (Order order : orderList) {
         order.execute();
      }
      orderList.clear();
   }
}

ステップ 5

Broker クラスを使用してコマンドを受け入れ、実行します。

CommandPatternDemo.java

public class CommandPatternDemo {
   public static void main(String[] args) {
      Stock abcStock = new Stock();

      BuyStock buyStockOrder = new BuyStock(abcStock);
      SellStock sellStockOrder = new SellStock(abcStock);

      Broker broker = new Broker();
      broker.takeOrder(buyStockOrder);
      broker.takeOrder(sellStockOrder);

      broker.placeOrders();
   }
}

ステップ 6

出力を確認します。

りー