[iOS 8] Swiftでデザインパターン No.6 Strategy

2014.10.27

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Strategy

Strategy とは

英単語 Strategy には以下のような意味があります。

  • 戦略

Strategy パターンは、アルゴリズムを実行時に選択することができるパターンです。

クラス図

strategy

ポイント

  • ConcreteStrategyA, ConcreteStrategyB で、それぞれ具体的な戦略を実装する

サンプルコード

Context

class Context {
private let strategy: Strategy

init(strategy: Strategy) {
self.strategy = strategy
}

func executeStrategy(#num1: Int, num2: Int) -> Int {
return strategy.execute(num1: num1, num2: num2)
}
}

Context は、イニシャライザで Strategy プロトコルを採用しているオブジェクトを受け取り、メンバ変数に保持します。 「#」については後述します。

Strategy

protocol Strategy {
func execute(#num1: Int, num2: Int) -> Int
}

Strategy はインターフェースなので、プロトコルとして記述します。

Add

class Add: Strategy {
func execute(#num1: Int, num2: Int) -> Int {
return num1 + num2
}
}

Add クラスは ConcreteStrategyA に相当します。 Strategy プロトコルを採用する、足し算を実装する戦略クラスです。

Subtract

class Subtract: Strategy {
func execute(#num1: Int, num2: Int) -> Int {
return num1 - num2
}
}

Subtract クラスは ConcreteStrategyB に相当します。 Strategy プロトコルを採用する、引き算を実装する戦略クラスです。

実行

var context: Context

context = Context(strategy: Add())
let addResult = context.executeStrategy(num1: 2, num2: 4)
println("Add result = (addResult)")

context = Context(strategy: Subtract())
let subtractResult = context.executeStrategy(num1: 2, num2: 4)
println("Subtract result = (subtractResult)")

実行結果

Add result = 6
Subtract result = -2

Strategy パターンを利用することで、利用するクライアントからは独立して、アルゴリズムを変更することができるようになります。

謎の文字「#」

「#」は Shorthand External Parameter Names というものを表現するシンボルです。

External Parameter Names

日本語で表すと「外部引数名」でしょうか。

let addResult = context.executeStrategy(num1: 2, num2: 4)

上記の例で言えば、num1 や num2 の部分が、外部引数名に該当します。 Swift ではメソッドの引数名を外部用と内部用で別々に持つことが可能です。

func test(a: Int, b: Int) {}

上記のようなメソッドが存在する場合、利用する側は通常以下のように記述しなければなりません。

test(2, b: 4)

これだと第一引数の名前が見えず、理解しづらいことがあります。 そんな時は以下のように書くことで引数名を表示させることができます。

// メソッド定義
func test(a a: Int, b: Int) {}

// 利用する側
test(a: 2, b: 4)

最初の「a」が外部引数名、次の「a」が内部引数名となります。 また、外部引数名と内部引数名が同じ場合は更に短く以下のように書くことができます。

func test(#a: Int, b: Int) {}

この「#」が、Shorthand External Parameter Names と呼ばれるものの正体です。

まとめ

  • Swift では外部引数名と内部引数名を別々に定義することができる
  • 「#」は Shorthand External Parameter Names を表現するシンボル
  • イニシャライザでは自動で外部引数名が設定される

リンク