最後に、生成処理をFactoryMethodパターンを使ってリファクタリングしようと思います。
FactoryMethodパターンとはGoFデザインパターンの1つで、オブジェクトの生成に関するものです。Charの生成処理をFactoryに持たせることで分岐を減らそうと思います。
まずは、「CharFactory.swift」を作って以下のように書いてください。
class CharFactory { func createChar() -> Char { return Char() } } class Char1Factory: CharFactory { override func createChar() -> Char { return Char1() } } class Char2Factory: CharFactory { override func createChar() -> Char { return Char2() } } class Char3Factory: CharFactory { override func createChar() -> Char { return Char3() } }
次に自機をセットする処理を修正します。SetCharScene.swiftを修正します。
class SetCharScene: SKScene { var coin = 100 var charData = [(factory: CharFactory, position: CGPoint)]() // 省略 override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) { if touches.count == 1, let point = touches.first?.locationInNode(self) { let alert = UIAlertController(title: nil, message: "どのキャラクターを設置しますか?", preferredStyle: .Alert) let rootViewController = UIApplication.sharedApplication().delegate?.window??.rootViewController alert.addAction(UIAlertAction(title: "Char1を設置", style: .Default, handler: { _ in let factory = Char1Factory() let char = factory.createChar() char.position = point self.coin -= char.cost self.addChild(char) self.charData.append((factory: factory, position: point)) })) alert.addAction(UIAlertAction(title: "Char2を設置", style: .Default, handler: { _ in let factory = Char2Factory() let char = factory.createChar() char.position = point self.coin -= char.cost self.addChild(char) self.charData.append((factory: factory, position: point)) })) alert.addAction(UIAlertAction(title: "Char3を設置", style: .Default, handler: { _ in let factory = Char3Factory() let char = Char3() char.position = point self.coin -= char.cost self.addChild(char) self.charData.append((factory: factory, position: point)) })) alert.addAction(UIAlertAction(title: "キャンセル", style: .Cancel, handler: nil)) rootViewController?.presentViewController(alert, animated: true, completion: nil) } } }
次にGameSceneのcreateCharsも少し修正します。今まであった分岐がなくなりすっきりとしました。
class GameScene: SKScene, SKPhysicsContactDelegate { // 省略 func createChars(charData: [(factory: CharFactory, position: CGPoint)]) { charData.forEach { let char = $0.factory.createChar() char.position = $0.position char.physicsBody = SKPhysicsBody(rectangleOfSize: char.size) char.physicsBody?.contactTestBitMask = 0x1 addChild(char) chars.append(char) } } // 省略 }
以上でFactoryMethodパターンを使った書き換えは終了です。FactoryMethodパターンを使ったことで「どのCharを生成するか」の処理をSetCharSceneだけに持たせることができました。これによって、今後Charの種類が増えたときもSetCharSceneの変更だけで済むようになりました。
FactoryMethodパターンは局所的なパターンで、とても使いやすいので、機会あればぜひ試してみてください。
今回はFactoryMethodパターンを使いつつ自機の配置周りの改善を行ってきました。
今回実装したソースコード「konkai.zip」は、こちらからダウンロードできます。
次回はタワーディフェンスとして不足している機能の実装を進めてゲームとしての完成度を高めていきます。iOS 9から登場したゲーム録画機能ができるReplayKitも使っていくので、どうぞお楽しみに。
田町のベンチャーで働くエンジニア。
仕事ではiPhoneアプリの開発やRailsを使ったWebサービス開発を行っている。最近のマイブームはUnityを使った3Dゲーム開発。
Copyright © ITmedia, Inc. All Rights Reserved.