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