【デザインパターン】Commandパターンをクラス図で理解する

デザインパターン

Commandパターン

Commandパターンは、処理の呼び出し(命令)と、処理の内容を分離するデザインパターンです。
自分なりにCommandパターンをクラス図にまとめてみました。

Commandパターンのクラス図

Commandパターンのクラス図

Commandパターンのクラス図

Commandパターンのクラス図の解説

例えば処理1→処理2という一連の処理を行う場合に、
処理1の処理内容をReceiver1のactionメソッドで定義し、処理2の処理内容をReceiver2のactionメソッドで定義をします。
一方、各々の実行を命令するオブジェクトとして、Command1,2クラスを作成します。具体的には、Command1,2のexecuteメソッドで、属性receiverのactionメソッドを呼び出すようにします。命令の仕方が1パターンの場合は具象Commandクラスは1つで構いませんが、命令の仕方が異なる場合(例えばCommand1は命令実行前にログを残し、Command2は命令実行後にメール通知をするなど)は、Commandクラスも複数用意しておいた方が分かりやすいでしょう。
そして、このCommandオブジェクトの配列を属性にもつInvokerクラスのexecuteメソッドで、commandsの中身の各Commandオブジェクトのexecuteメソッドを実行すれば、格納した順番に処理が実行できます。

このような構成にすることで、処理1→処理2ではなく、処理2→処理1にしたい場合や、処理1→処理2→処理1にしたい場合がでてきても、Invoker側のcommands配列を変更するだけで対応ができます。また、命令の仕方を変えたい場合、処理の内容を変えたい場合にも、それぞれCommandクラス、Receiverクラスを追加・変更すれば対応でき、それぞれの依存関係を疎にすることができます。

Commandパターンをどういう場合に使うか

オフィスツールでは操作履歴がどんどんスタックされていき、Undo、Redoを使って命令を戻ったり進んだりできますが、そのように命令の順番を意識するような場合にCommandパターンは有効です。

PlantUMLでCommandパターンのクラス図を記述する

Commandパターンのクラス図をPlantUMLで書いたときのソースです。

@startuml Command
interface Command{
  {abstract}execute() : void
}
class Command1 implements Command{
  + receiver : Receiver
  execute() : void
}
class Command2 implements Command{
  + receiver : Receiver
  execute() : void
}
abstract class Receiver{
  + {abstract} action()
}
class Receiver1 extends Receiver{
  + action()
}
class Receiver2 extends Receiver{
  + action()
}
class Invoker{
  + commands : Command[]
  --
  + addCommand(Command) : void
  + deleteCommand(Command) : void
  + execute() : void
}
Invoker o--> Command
Command1 o--> Receiver
Command2 o--> Receiver
@enduml

参考サイトURL

Command パターン – デザインパターン入門 – IT専科
デザインパターン ~Command~ – Qiita