Abstract Factory パターン とは
概要
Wikipediaによると、
「関連するインスタンス群を生成するための API を集約することによって、複数のモジュール群の再利用を効率化することを目的とする。」デザインパターンのことです。
SwiftにおけるAbstract Factory パターン
iOSアプリ開発で活用する場合、VCやViewなどが生成したい「モノ」の具象クラスを意識せずに、共通のプロトコルに準拠したインスタンスを取得するために使えます。
オブジェクト生成の責務をView側から切り離すとともに、インスタンス化をカプセル化(秘匿化)することが可能です。
インスタンスの生成に関する修正が発生したときに、View側を触らなくていいというのも良きですね。
実装例
今回は、飲料水を製造する工場を例として考えました。
工場に渡した材料によって、異なる飲み物を提供するというサンプルプログラムを書きました。
「ビールクラス」と「りんごジュースクラス」はそれぞれ「飲み物プロトコル」に準拠しています。
SampleCode
// MARK: 工場のインターフェース
protocol DrinkFactoryProtocol {
func create() -> Drink
}
// MARK: 工場の具象クラス
class BeerFactory: DrinkFactoryProtocol {
func create() -> Drink {
return Beer()
}
}
class AppleJuiceFactory: DrinkFactoryProtocol {
func create() -> Drink {
return AppleJuice()
}
}
// MARK: 飲み物のインターフェース
protocol Drink: AnyObject {
var name: String { get }
func served(age: Int) -> String
}
// MARK: 飲み物の具象クラス
class Beer: Drink {
var name: String = "ビール"
func served(age: Int) -> String {
return age >= 20 ? "美味しいビールができました。" : "20歳に満たないため、提供できません。"
}
}
class AppleJuice: Drink {
var name: String = "りんごジュース"
func served(age: Int) -> String {
return "100%のりんごジュースです。"
}
}
// MARK: use
// ここでは、注文された飲み物によって生成するインスタンスを決定する工場全体の役割
class DrinkFactory: DrinkFactoryProtocol {
let drink: InStockDrink
enum InStockDrink {
case beer
case applejuice
}
init(ordered: InStockDrink) {
self.drink = ordered
}
func create() -> Drink {
switch drink {
case .beer:
return BeerFactory().create()
case .applejuice:
return AppleJuiceFactory().create()
}
}
}
let factory = DrinkFactory(ordered: .beer)
let drink = factory.create()
print(drink.served(age: 18)) // 20歳に満たないため、提供できません。
コードをみればおわかりかと思いますが、インスタンス生成時に、具象クラスを意識しなくても、何かしらの引数を渡せばそれに適したインスタンスが戻ってくるという構造ができあがっています。
以上です!