元ネタ → ochococo/Design-Patterns-In-Swift
クラス図
図の引用元:Wikipedia: Strategy パターン
概要
The strategy pattern is used to create an interchangeable family of algorithms from which the required process is chosen at run-time.
Strategyパターンは、アルゴリズムが交換可能なファミリを作成しておき、それらの中から実行時に必要なプロセスが選択されるように利用する。
ファミリはStrategyで必要なプロセスの定義をしている。ファミリの構成員はConcreteStrategyA/Bで必要なプロセスをアルゴリズムとして実装している。
サンプルコード
struct TestSubject {
let pupilDiameter: Double
let blushResponse: Double
let isOrganic: Bool
}
// Strategy
protocol RealnessTesting: AnyObject {
// AlgorithmInterface()
func testRealness(_ testSubject: TestSubject) -> Bool
}
// ConcreteStrategyA
final class VoightKampffTest: RealnessTesting {
// AlgorithmInterface()
func testRealness(_ testSubject: TestSubject) -> Bool {
return testSubject.pupilDiameter < 30.0 || testSubject.blushResponse == 0.0
}
}
// ConcreteStrategyB
final class GeneticTest: RealnessTesting {
// AlgorithmInterface()
func testRealness(_ testSubject: TestSubject) -> Bool {
return testSubject.isOrganic
}
}
// Context
final class BladeRunner {
// Containment
private let strategy: RealnessTesting
init(test: RealnessTesting) {
self.strategy = test
}
// ContextInterface
func testIfAndroid(_ testSubject: TestSubject) -> Bool {
return !strategy.testRealness(testSubject)
}
}
// usage //
let rachel = TestSubject(pupilDiameter: 30.2,
blushResponse: 0.3,
isOrganic: false)
// Deckard is using a traditional test
let deckard = BladeRunner(test: VoightKampffTest())
let isRachelAndroid = deckard.testIfAndroid(rachel)
// Gaff is using a very precise method
let gaff = BladeRunner(test: GeneticTest())
let isDeckardAndroid = gaff.testIfAndroid(rachel)
クラス図との対応
| サンプルコード | クラス図 |
|---|---|
| RealnessTesting | Strategy |
| testRealness | AlgorithmInterface |
| サンプルコード | クラス図 |
|---|---|
| VoightKampffTest, GeneticTest | ConcreteStrategy |
| testRealness | AlgorithmInterface |
| サンプルコード | クラス図 |
|---|---|
| BladeRunner | Context |
| strategy | Containment(集約) |
| testIfAndroid | ContextInterface |
考察
Strategyパターンは、アルゴリズムが交換可能なファミリを作成しておき、それらの中から実行時に必要なプロセスが選択されるように利用する。
ファミリはStrategy、必要なプロセスを定義をしている。ファミリの構成員はConcreteStrategyA/B、必要なプロセスの定義に準拠した具体的なアルゴリズムとして実装することで交換可能になっている(ポリモフィズム)。ContextはプロパティとしてStrategyのインスタンスstrategyを持ち(集約/aggregate、アップキャスト)、ContextInterfaceの実態はこのstrategyのAlgorithmInterfaceである。Contextのインスタンス生成時(実行時)に、集約しているstrategyを決定することでContextInterfaceの実行内容(必要なプロセス)も決定される(ポリモフィズム)。
