[์ค์ํํธ ๋์์ธํจํด] ์ถ์ ํฉํ ๋ฆฌ ํจํด(Abstract Factory Pattern)
์ถ์ ํฉํ ๋ฆฌ ํจํด
The abstract factory pattern provides an interface of creating families of related or dependent objects without specifying their concrete classes.
์ด์ ํฌ์คํธ์์ ํฉํ ๋ฆฌ ๋ฉ์๋ ํจํด์ ๋ํด ์ ๋ฆฌํด๋ณด์๋๋ฐ์, ์ถ์ ํฉํ ๋ฆฌ ํจํด์ ํฉํ ๋ฆฌ ๋ฉ์๋ ํจํด๊ณผ ์์ฃผ ์ ์ฌํฉ๋๋ค. ๋ ๋์์ธ ํจํด์ ์ฐจ์ด๋ฅผ ์ด์ผ๊ธฐ ํ๋ค๋ฉด ํฉํ ๋ฆฌ ๋ฉ์๋ ํจํด์ ํ๋์ ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ธฐ ์ํด ์ฌ์ฉํ๊ณ , ์ถ์ ํฉํ ๋ฆฌ ํจํด์ ์ฌ๋ฌ๊ฐ์ ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ธฐ ์ํด์ ์ฌ์ฉํ๋ค๊ณ ํ ์ ์์ด์.
์ฌ์ค ๊ธฐ์ ์ ์ผ๋ก๋ ํฉํ ๋ฆฌ ๋ฉ์๋ ํจํด๊ณผ ์ถ์ ํฉํ ๋ฆฌ ํจํด์ด ๋ค๋ฅธ ์ ์ด ์์ด์. ์์กด์ฑ ์ฃผ์ ๊ด์ ์์๋ ๊ฐ์ ์ญํ ์ ํ๊ธฐ ๋๋ฌธ์ด์ฃ . ํ์ง๋ง ์ฉ๋์ ๋ฐ๋ผ์ ํฉํ ๋ฆฌ ๋ฉ์๋ ํจํด๊ณผ ์ถ์ ํฉํ ๋ฆฌ ํจํด์ด ๊ฐ๊ฐ ๋ ์ ์ฉํ๊ฒ ์ฌ์ฉ๋ ์ ์์ต๋๋ค.
ํฉํ ๋ฆฌ ๋ฉ์๋ ํจํด vs. ์ถ์ ํฉํ ๋ฆฌ ํจํด
์ถ์ ํฉํ ๋ฆฌ ํจํด์ ๋ํด ์ด์ผ๊ธฐํ๊ธฐ ์ํด์ ํฉํ ๋ฆฌ ๋ฉ์๋ ํจํด์ ์งง๊ฒ ์ ๋ฆฌํด๋ณด๊ณ ์ด๋ป๊ฒ ์ถ์ ํฉํ ๋ฆฌ ํจํด์ด ๋ค๋ฅธ์ง ์ดํดํด๋ณผ๊ฒ์.
ํฉํ ๋ฆฌ ๋ฉ์๋ ํจํด์ ํฉํ ๋ฆฌ์ ์ญํ ์ ํ๋ Creator๊ฐ ์๊ณ , factoryMethod๋ฅผ ํตํด ์ด๋ค ๊ฐ์ฒด์ ์ธ์คํด์ค๋ฅผ ์์ฑํ๋๋กํฉ๋๋ค. ํฉํ ๋ฆฌ ๋ฉ์๋ ํจํด์์๋ ํ ๋ฒ์ ํ๋์ ๊ฐ์ฒด๋ง ์์ฑ๋๊ธฐ ๋๋ฌธ์ ์์ฑ๋๋ ๋ชจ๋ Concrete Product๋ค์ด ์๋ก ๋ ๋ฆฝ์ ์ ๋๋ค.
์ด์ ์ฌ๋ฌ ๊ฐ์ ๊ฐ์ฒด๋ฅผ ํ ๋ฒ์ ์์ฑํด์ผํ๋ ์ํฉ์ ์๊ฐํด๋ณผ๊ฒ์.
์ด๋ ๊ฒ ์ด๋ค UI๋ฅผ ๋ง๋ค๊ธฐ ์ํด์ 4๊ฐ์ ๊ฐ์ฒด ์ค ๋ ๊ฐ๋ฅผ ์ ํํด ์กฐํฉํ๋ค๊ณ ํด๋ณผ๊ฒ์. BlackView๋ ๋น์ฐํ YellowButton๊ณผ ์กฐํฉ์ด ๋์ด์ผ ์ฌ์ฉ์ฑ์ด ์ข์ ๊ฒ์ด๊ณ , YellowView๋ BlackButton๊ณผ ์กฐํฉ์ด ๋์ด์ผ ์ฌ์ฉ์ฑ์ด ์ข๊ฒ ์ฃ . ๊ทธ๋์ ์ฐ๋ฆฌ๋ BlackView์ BlackButton, YellowView์ YellowButton์ด ์ค์๋ก๋ผ๋ ์กฐํฉ๋์ง ์๊ธฐ๋ฅผ ์ํฉ๋๋ค.
ํฉํ ๋ฆฌ ๋ฉ์๋ ํจํด์ ์ฌ์ฉํ๋ฉด ๊ฐ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ํฉํ ๋ฆฌ๋ฅผ ๋ง๋ค ์ ์๊ฒ ์ฃ ?
์ด๋ ๊ฒ ๋ฒํผ์ ์์ฑํ๋ ํฉํ ๋ฆฌ, ๋ทฐ๋ฅผ ์์ฑํ๋ ํฉํ ๋ฆฌ๋ฅผ ๊ฐ๊ฐ ๋ง๋ค์ด์ ๊ฐ์ฒด๋ฅผ ์์ฑํ ์ ์๊ฒ ์ฃ . ํ์ง๋ง ์ด ํฉํ ๋ฆฌ๋ฅผ ํตํด์๋ ๋ฐ๋์ ๋ ธ๋์+๊ฒ์์์ด ์กฐํฉ๋๋๋ก ํ ์๋ ์์ต๋๋ค.
์ด๋ ๊ฒ ์ด๋ค ๊ฐ์ฒด๋ค์ด ์๋ก ์์กด์ฑ์ ๊ฐ์ง๊ฑฐ๋ ํจ๊ป ์ฌ์ฉ๋์ด์ผ ํ ๋, ์ถ์ ํฉํ ๋ฆฌ ํจํด์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ๋ฒํผ์ ๋ง๋๋ ํฉํ ๋ฆฌ, ๋ทฐ๋ฅผ ๋ง๋๋ ํฉํ ๋ฆฌ๋ฅผ ๋ฐ๋ก ๋๋ ๊ฒ์ด ์๋๋ผ ๋ ธ๋์ ๋ฒํผ๊ณผ ๊ฒ์์ ๋ทฐ๋ฅผ ๋ง๋๋ ํฉํ ๋ฆฌ, ๊ทธ๋ฆฌ๊ณ ๊ฒ์์ ๋ฒํผ๊ณผ ๋ ธ๋์ ๋ทฐ๋ฅผ ๋ง๋๋ ํฉํ ๋ฆฌ๋ฅผ ๋๋ ๊ฒ์ด์ฃ . ํฌ์คํธ ๊ฐ์ฅ ์ฒ์์ ์ ์๋ "families of related or dependent objects" ๊ฐ ์ด๋ฐ ์๋ฏธ์ ๋๋ค.
๋จผ์ ButtonBoxFactory๋ผ๋ ์ธํฐํ์ด์ค๋ฅผ ์ ์ํ๊ณ ๋ด๋ถ์ ๋ ๊ฐ์ ๋ฉ์๋๋ฅผ ์ถ๊ฐํฉ๋๋ค. ๋ฉ์๋๋ ๋ทฐ๋ฅผ ๋ง๋ค๊ธฐ ์ํ ๋ฉ์๋์ ์ธํฐํ์ด์ค, ๋ฒํผ์ ๋ง๋ค๊ธฐ ์ํ ์ธํฐํ์ด์ค์ด์ฃ .
์ด ํ๋กํ ์ฝ์ ์ฑํํ๋ DarkButtonBoxFactory๋ ๊ฒ์์ ๋ทฐ๋ฅผ ๋ง๋ค์ด ๋ฐํํ๊ณ , ๋ ธ๋์ ๋ฒํผ์ ๋ง๋ค์ด ๋ฐํํ๋๋ก ๊ตฌํํฉ๋๋ค. ๊ทธ๋ผ ์ด์ ๋ ์ด ํฉํ ๋ฆฌ๋ฅผ ํตํด์ ๋ฐ๋์ ๊ฒ์์ ๋ทฐ์ ๋ ธ๋์ ๋ฒํผ์ ์กฐํฉ์ ์์ฑํ ์ ์์ต๋๋ค.
๊ฐ์ ๋ฐฉ๋ฒ์ผ๋ก LightButtonBoxFactory๋ ๋ ธ๋์ ๋ทฐ์ ๊ฒ์์ ๋ฒํผ์ ๋ง๋ค์ด ๋ฐํํ๋๋ก ๋ฉ์๋๋ฅผ ๊ตฌํํฉ๋๋ค. ๋ฐ๋ผ์ ์ด ํฉํ ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ฉด ํญ์ ๋ ธ๋์ ๋ทฐ์ ๊ฒ์์ ๋ฒํผ์ ์กฐํฉ์ ๋ง๋ค ์ ์์ต๋๋ค.
๊ตฌํํด๋ณด๊ธฐ
์ ์์๋ฅผ ๊ทธ๋๋ก ๊ตฌํํด๋ณผ๊ฒ์.
๋จผ์ Product์ธ View, Button๊ณผ Concrete Product์ธ YellowView, BlackView, YellowButton, BlackButton์ ๋ง๋ค์ด์ค์๋ค.
import Foundation
protocol View: CustomStringConvertible {
var id: String { get set }
var color: String { get set }
}
extension View {
var description: String {
return "type: view id: \(id) color \(color)"
}
}
protocol Button: CustomStringConvertible {
var id: String { get set }
var color: String { get set }
}
extension Button {
var description: String {
return "type: button id: \(id) color \(color)"
}
}
class YellowView: View {
var id: String
var color: String = "Yellow"
init(id: String) {
self.id = id
}
}
class BlackView: View {
var id: String
var color: String = "Black"
init(id: String) {
self.id = id
}
}
class YellowButton: Button {
var id: String
var color: String = "Yellow"
init(id: String) {
self.id = id
}
}
class BlackButton: Button {
var id: String
var color: String = "Black"
init(id: String) {
self.id = id
}
}
let blackButton = BlackButton(id: "bb")
let yellowButton = YellowButton(id: "yb")
let blackView = BlackView(id: "bv")
let yellowView = YellowView(id: "yv")
print("\(blackView)\n\(blackButton)\n\(yellowView)\n\(yellowButton)")
// type: view id: bv color Black
// type: button id: bb color Black
// type: view id: yv color Yellow
// type: button id: yb color Yellow
// Program ended with exit code: 0
๊ฐ๋จํ์ฃ ? ์ฌ๊ธฐ์ ๊ฐ Concrete Product์ ๋ํ ํฉํ ๋ฆฌ๋ฅผ ๋ง๋ค์ด์ฃผ๋ฉด ํฉํ ๋ฆฌ ๋ฉ์๋ ํจํด์ด ๋๊ณ , ์ถ์ ํฉํ ๋ฆฌ ํจํด์ ์๋ก ์ฐ๊ด๋ ๋ค์์ ๊ฐ์ฒด๋ฅผ ์์ฑํ ์ ์๋ ํฉํ ๋ฆฌ๋ฅผ ๋ง๋๋ ๊ฒ์ด์์ต๋๋ค.
protocol ButtonBoxFactory {
func createView() -> View
func createButton() -> Button
}
class DarkButtonBoxFactory: ButtonBoxFactory {
func createView() -> View {
return BlackView(id: "bv")
}
func createButton() -> Button {
return YellowButton(id: "yb")
}
}
class LightButtonBoxFactory: ButtonBoxFactory {
func createView() -> View {
return YellowView(id: "yv")
}
func createButton() -> Button {
return BlackButton(id: "bb")
}
}
์ฒ์ ์ค๊ณํ๋๋๋ก ๋ ๊ฐ์ ํฉํ ๋ฆฌ๋ฅผ ๋ง๋ค์๊ณ , ๊ฐ ํฉํ ๋ฆฌ์์ ๋คํฌ๋ชจ๋, ๋ผ์ดํธ๋ชจ๋์ ๋ง๋ ๋ทฐ์ ๋ฒํผ ๊ฐ์ฒด๋ฅผ ์์ฑํด ๋ฐํํ ์ ์๊ฒ ํ์ต๋๋ค.
๊ทธ๋ผ ์ด์ ํด๋ผ์ด์ธํธ ๊ฐ์ฒด๋ฅผ ์์ฑํด์ ์ถ์ํฉํ ๋ฆฌ ํจํด์ด ์ ์ ์ฉํ์ง ์ง์ ๋๊ปด๋ณด์ฃ !
class ButtonBox {
enum ColorTheme {
case dark, light
}
private var colorTheme: ColorTheme
private var buttonBoxFacotry: ButtonBoxFactory
private var button: Button?
private var view: View?
init(colorTheme: ColorTheme) {
self.colorTheme = colorTheme
self.buttonBoxFacotry = colorTheme == .dark ? DarkButtonBoxFactory() : LightButtonBoxFactory()
self.createButtonBox()
}
private func createButtonBox() {
self.button = buttonBoxFacotry.createButton()
self.view = buttonBoxFacotry.createView()
}
func change(colorTheme: ColorTheme) {
self.colorTheme = colorTheme
self.buttonBoxFacotry = colorTheme == .dark ? DarkButtonBoxFactory() : LightButtonBoxFactory()
self.createButtonBox()
}
func printComponents() {
print(self.view!)
print(self.button!)
}
}
ButtonBox๋ผ๋ ํด๋์ค๋ฅผ ํ๋ ๋ง๋ค์๊ตฌ์, ์ธ์๋ก ์ฃผ์ด์ง๋ ์์ ํ ๋ง ์ ๋ณด๋ฅผ ํตํด ํฉํ ๋ฆฌ๊ฐ ๋ณ๊ฒฝ๋๋๋ก ํ์ต๋๋ค. ButtonBox๋ฅผ ์ํด ํ์ํ ๋ ๊ฐ์ฒด์ธ View์ Button์ ์์ฑ๋ ํฉํ ๋ฆฌ๋ฅผ ํตํด ๋ง๋ค์ด์ง๋๋ค.
๋ง์ฝ ์ด๋ค ํ ๋ง์์ ์์ฑํด์ผํ๋ ๊ฐ์ฒด ๋ฌ๋ผ์ง๋ค๋ฉด ButtonBox๊ฐ ์๋๋ผ ButtonBoxFactory๋ก ์ฐพ์๊ฐ ๊ฐ์ฒด๋ฅผ ์์ ํด์ฃผ๋ฉด ๋๊ฒ ์ฃ ? ๊ทธ๋ฆฌ๊ณ change ๋ฉ์๋๋ฅผ ํ๋ ๋ง๋ค์ด์ ์ ์ฐํ๊ฒ ๋ชจ๋์ ๋ฐ๋ผ ๋ค๋ฅธ ๊ฐ์ฒด๊ฐ ์ฝ๊ฒ ์์ฑ๋ ์ ์๋๋ก ๋ง๋ค ์๋ ์์์ต๋๋ค.
var buttonBox = ButtonBox(colorTheme: .dark)
buttonBox.printComponents()
print("\n## Change Factory ##\n")
buttonBox.change(colorTheme: .light)
buttonBox.printComponents()
// type: view id: bv color Black
// type: button id: yb color Yellow
//
// ## Change Factory ##
//
// type: view id: yv color Yellow
// type: button id: bb color Black
// Program ended with exit code: 0
ButtonBox์ ์ธ์คํด์ค๋ฅผ ์์ฑํด์ ์ฌ์ฉํ ๋๋, ์ด๋ ๊ฒ ๊ฐ๋จํ๊ฒ ๊ฐ ํ ๋ง์ ๋ง๋ ๊ฐ์ฒด๋ฅผ ์์ฑํด ์ฃผ์ ํด์ค ์ ์๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
๋ง๋ฌด๋ฆฌ
๊ฒฐ๊ตญ ์ถ์ ํฉํ ๋ฆฌ ํจํด์ด ํฉํ ๋ฆฌ ๋ฉ์๋ ํจํด์ผ๋ก๋ถํฐ ๊ตฌ๋ณ๋๋ ๊ฐ์ฅ ํฐ ํน์ง์ ํ ํฉํ ๋ฆฌ์์ ์ฌ๋ฌ ์ข ๋ฅ(Product)์ ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ , ์ด ๊ฐ์ฒด๋ค์ด ์๋ก ์ฐ๊ด๋์ด ์๊ฑฐ๋ ์์กด์ฑ์ ๊ฐ์ง๊ณ ์๋๋ค๋ ๊ฒ์ ๋๋ค. ๋ฐ๋ผ์ ๋จ์ํ ์์ฑ๊ณผ ์ฃผ์ ์ ์ญํ ๋ง์ ํ๋ ๊ฒ์ด ์๋๋ผ ๊ฐ์ฒด๋ค์ ์ญํ ์ ๋ฐ๋ผ ์์ง์ํค๋ ์ญํ ๋ ํ๊ณ ์๋ ๊ฒ์ด์ฃ .
๊ฝค ํท๊ฐ๋ ธ๋ ํฉํ ๋ฆฌ ํจํด, ํฉํ ๋ฆฌ ๋ฉ์๋ ํจํด, ์ถ์ ํฉํ ๋ฆฌ ํจํด์ ์ ๋ฆฌ๊ฐ ์ด๋ ๊ฒ ๋ง๋ฌด๋ฆฌ๋์์ต๋๋ค. ํน์๋ผ๋ ์๋ชป๋ ์ ๋ณด๊ฐ ์๊ฑฐ๋ ๋ค๋ฅธ ์๊ฒฌ์ด ์์ผ์๋ค๋ฉด ์๋ ค์ฃผ์ธ์! ์ ๋ ๋ ๊ณ ๋ฏผํด๋ณด๊ณ ์์ ํ๋๋กํ๊ฒ ์ต๋๋ค.
์ค๋๋ ์ฝ์ด์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค!
'๐ฎ ์จ-์์ค > ๐ ๋์์ธํจํด' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๋๊ธ
์ด ๊ธ ๊ณต์ ํ๊ธฐ
-
๊ตฌ๋
ํ๊ธฐ
๊ตฌ๋ ํ๊ธฐ
-
์นด์นด์คํก
์นด์นด์คํก
-
๋ผ์ธ
๋ผ์ธ
-
ํธ์ํฐ
ํธ์ํฐ
-
Facebook
Facebook
-
์นด์นด์ค์คํ ๋ฆฌ
์นด์นด์ค์คํ ๋ฆฌ
-
๋ฐด๋
๋ฐด๋
-
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
-
Pocket
Pocket
-
Evernote
Evernote