デザインパターンの1つであるStrategyパターンについて自分なりにまとめてみました。
Strategyパターンのクラス図
Strategyパターンの解説
Strategyクラスが抽象クラスで、ここに定義したメソッドをStrategyを継承するStrategy1、Strategy2クラスで実装する。上のクラス図では仮にfuncメソッドとしているが、このメソッドは何でも構わない。
Contextクラスは属性にStrategy型を持つ(strategyとしている)。コンストラクタなどで属性のstrategyにStrategy1,Strategy2をインスタンス化したオブジェクトを代入しておく。Contextオブジェクトのcallメソッドの内部でstrategyのfuncメソッドを呼び出すと、strategyがStrategy1型かStrategy2型かによってどちらかのfuncメソッドが呼び出される。
funcメソッドは仮のEntity型の変数を戻り値として定義している。実際にはEntityクラスの定義が必要だが今回はStrategyパターンとは関係ないのでクラス図には含めていない。Entity1,Entity2はEntityを継承しているクラスだと考えてもらえればよい。
パターンをどういう場合に使うか
例えばファイルアップロードされた場合に、PDFだったらこの処理、エクセルだったら別処理、・・・といったようにファイル形式毎に処理が異なるような場合、Contextクラスでアップロードのリクエストを受け取るとすると、Contextのメソッド内でif文を作りアップロードファイルの形式を判定し、各々の処理を行うことが可能である。が、ファイル形式がもっと増えていった場合、Contextのメソッド内で完結させようとするとメソッドが肥大化していく。その各々の処理をStrategyクラス側に任せることで、Context側ではどのStrategyを使うか、だけを決めればよくなるので、処理の見通しが良くなる。
StrategyパターンのPlantUMLの記述
文頭のStrategyパターンのクラス図をPlantUMLで書いたときのソースです。
@startuml Strategy Method
abstract class Strategy{
--
# {abstract} Entity func()
}
class Strategy1 extends Strategy{
--
# Entity1 func()
}
class Strategy2 extends Strategy{
--
# Entity2 func()
}
class Context{
- strategy : Strategy
--
# Entity call()
}
Context o-r- Strategy : contain >
@enduml