はじめに
本記事では、GoFの23種類のデザインパターンの1つでもある、FactoryMethodパターンについて書いてみました。
FactoryMethodパターンとは
概要
「インスタンスの生成をサブクラスに実行させ、柔軟にインスタンス生成を行うためのパターン」のことです。
インスタンスを生成する側は、インスタンスについて直接意識しなくても、利用することができます。(Protocolを介しているため)
このパターンの進化前(?)のパターンで、Factoryパターン(SimpleFactory)というのがあります。
Factoryパターンは、1つのファクトリの中で、オブジェクトの種類の選択を動的に行うことが特徴です。
それに対し、FactoryMethodパターンでは、生成するオブジェクトごとに、Factoryクラスを用意することで、コードの冗長化や柔軟性を高めていることが特徴です。
SwiftにおけるFactoryMethodパターン
個人的な意見として、Swiftはenum型
が強すぎて、Factoryパターンのほうが使用頻度が高い気がします。
Factoryパターンについては、下記をご覧ください。
実装してみた
今回のケースは、
従業員が職種別に存在する会社がある。
その会社の社員を職種で判断し、仕事(Task)を実行させたいと思います。
import UIKit
// MARK: Product(インスタンス化される側)のプロトコル
protocol Employee: AnyObject {
var name: String { get set }
var department: String { get }
func executeTask()
}
// MARK: Creator(インスタンス化する側)のプロトコル
protocol Factory: AnyObject {
func create(name: String) -> Employee
func createEmployee(name: String) -> Employee
func registerEmployee(_ employee: Employee)
}
// MARK: Productを実装した具象クラス
class Developer: Employee {
var name: String
var department: String {
return "開発部"
}
init(name: String) {
self.name = name
}
func executeTask() {
print("\(department)の\(name)は、コーディングを行います。")
}
}
// MARK: Creatorを実装した具象クラス
class DeveloperFactory: Factory {
var employeeList: [Employee] = []
func create(name: String) -> Employee {
let employee = createEmployee(name: name)
registerEmployee(employee)
return employee
}
func createEmployee(name: String) -> Employee {
return Developer(name: name)
}
func registerEmployee(_ employee: Employee) {
employeeList.append(employee)
}
}
// MARK: 実行
let factory = DeveloperFactory()
let emp1 = factory.create(name: "山田")
emp1.executeTask() // 開発部の山田は、コーディングを行います。
let emp2 = factory.create(name: "田中")
emp2.executeTask() // 開発部の田中は、コーディングを行います。
冒頭でも述べたように、生成するインスタンスごとに、Factoryクラスを追加するのが特徴であるため、もし営業部を追加したいということであればこんな感じで追加します。
class SalesPerson: Employee {
var name: String
var department: String {
return "営業部"
}
init(name: String) {
self.name = name
}
func executeTask() {
print("\(department)の\(name)は、得意先への訪問を行います。")
}
}
class SalesPersonFactory: Factory {
var employeeList: [Employee] = []
func create(name: String) -> Employee {
let employee = createEmployee(name: name)
registerEmployee(employee)
return employee
}
func createEmployee(name: String) -> Employee {
return SalesPerson(name: name)
}
func registerEmployee(_ employee: Employee) {
employeeList.append(employee)
}
}
// MARK: 実行
let salesFactory = SalesPersonFactory()
let emp3 = salesFactory.create(name: "佐藤")
emp3.executeTask()
以上!