この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
Builder
Builder とは
英単語 Build には以下のような意味があります。
- 組み立てる
- 建築する
Builder パターンは、オブジェクトの生成過程を抽象化することによって、動的なオブジェクトの生成を可能にするパターンです。
クラス図
ポイント
- 抽象クラス Builder の buildPart オペレーションはデフォルトでは何も行わない
- 各 ConcreteBuilder クラスが、生成する構成要素に対するオペレーションのみをオーバーライドする
サンプルコード
今回は「勇者」オブジェクトを生成し、以下の項目を設定するプログラムを考えてみました。
- レベル
- ぶき
- よろい
Builder
class Builder: NSObject {
func buildLevel(level: Int) {}
func buildSword(sword: String) {}
func buildArmor(armor: String) {}
}
こちらは Builder クラスです。 「レベル」、「ぶき」、「よろい」を設定するメソッドを持っています。
HeroBuilder
class HeroBuilder: Builder {
let hero = Hero()
override func buildLevel(level: Int) {
self.hero.level = level
}
override func buildSword(sword: String) {
self.hero.sword = sword
}
override func buildArmor(armor: String) {
self.hero.armor = armor
}
func getResult() -> Hero {
return self.hero
}
}
こちらは ConcreteBuilder クラスです。 「勇者」オブジェクトを構築するクラスです。
Hero
class Hero: NSObject {
var level: Int?
var sword: String?
var armor: String?
func showStatus() {
println("### Status ###")
println("Level: (self.level)")
println("Sword: (self.sword)")
println("Armor: (self.armor)")
println("##############")
}
func checkStatus() {
if let level = self.level, sword = self.sword, armor = self.armor where level > 10 {
println("そなたは もう じゅうぶんにつよい!")
} else {
println("レベルが あがったら また くるがいい")
println("ぶきや ぼうぐは そうびしないと いみがないぞ")
}
}
}
こちらは Product クラスです。 「勇者」を表します。 ステータスを表示するメソッド、ステータスをチェックするメソッドを持ちます。
Director
class Director: NSObject {
let builder: Builder
init(builder: Builder) {
self.builder = builder
}
func construct() {
self.builder.buildLevel(30)
self.builder.buildSword("おうじゃのけん")
self.builder.buildArmor("ひかりのよろい")
}
}
こちらは Director クラスです。 Builder クラスのインタフェースを使って「勇者」を生成します。
実行
let heroBuilder = HeroBuilder()
let director = Director(builder: heroBuilder)
director.construct()
let hero = heroBuilder.getResult()
hero.showStatus()
hero.checkStatus()
実行結果
### Status ###
Level: Optional(30)
Sword: Optional("おうじゃのけん")
Armor: Optional("ひかりのよろい")
##############
そなたは もう じゅうぶんにつよい!
オブジェクトを一度に作成するパターンとは違い、Builder パターンでは Product オブジェクトを段階的に作成します。 これにより Product オブジェクトの内部構造を、より細かくコントロールすることができるようになります。
余裕があれば、装備に「たて」や「かぶと」、キャラクターに「戦士」や「魔法使い」が追加された時についても考えてみましょう。
Multiple Optional Bindings
Hero クラスに無理やり作成した以下のメソッドに注目してください。
func checkStatus() {
if let level = self.level, sword = self.sword, armor = self.armor where level > 10 {
println("そなたは もう じゅうぶんにつよい!")
} else {
println("レベルが あがったら また くるがいい")
println("ぶきや ぼうぐは そうびしないと いみがないぞ")
}
}
ここでは Optional Bindings を使用していますが、Swift 1.2 からは複数の変数について一行の if 文で書けるようになりました。 ネストが深くなることがなくなるので、これは嬉しい進化ですね。(右に長くなってはしまいますが・・・)
まとめ
- Swift 1.2 からは複数の Optional Bindings に対応した!
- バインドした変数について条件式も同時に書ける!