모든 코드는 Swift로 작성되었습니다.
문제 상황
BlackView, BlackButton, YellowView, YellowButton 객체들을 조합하여 위 그림과 같은 조합의 객체를 생성해야 하는 상황이라고 가정해 보자.
각 객체들을 팩토리 메서드 패턴을 사용해서 생성하고자 한다면 아래 그림과 같이 BlackView와 YellowView는 View의 Concrete Product로 하고 ColoredViewFactory라는 Concrete Creator를 생성할 것이고, BlackButton과 YellowButton은 Button의 Concrete Product, ColoredButtonFactory를 Concrete Creator로 생성할 것이다.
하지만, 팩토리 메서드 패턴을 사용한다면, BlackView와 YellowButton의 조합 또는 YellowView와 BlackButton의 조합을 보장할 순 없을 것이다.
추상 팩토리 메서드 패턴
추상 팩토리 메서드 패턴은 팩토리 메서드 패턴 사용 중 서로 관련 있는 객체의 집합을 생성하고자 할 때 사용되는 디자인 패턴이다. 아래 그림과 같이 View와 Button의 Creator들을 한번 더 추상화함으로써 조합이 보장될 수 있게 해 준다. (그림에서 DarkButtonBoxFactory를 BlackViewYellowButtonFactory, LightButtonBoxFactory를 YellowViewBlackButtonFactory로 생각하면 이해하기 쉽다.)
코드 예시
Product와 Concrete Product
// ================= Product =================
protocol View {
func getViewColor() -> String
}
protocol Button {
func getButtonColor() -> String
}
// ================= Concrete Product =================
class YellowView: View {
private var viewColor = "Yellow"
func getViewColor() -> String {
return self.viewColor + "View"
}
}
class BlackView: View {
private var viewColor = "Black"
func getViewColor() -> String {
return self.viewColor + "View"
}
}
class YellowButton: Button {
private var buttonColor = "Yellow"
func getButtonColor() -> String {
return self.buttonColor + "Button"
}
}
class BlackButton: Button {
private var buttonColor = "Black"
func getButtonColor() -> String {
return self.buttonColor + "Button"
}
}
Creator와 Concrete Creator
protocol ViewButtonFactory { // Creator
func createView() -> View
func createButton() -> Button
}
class BlackViewYellowButtonFactory: ViewButtonFactory { // Concrete Creator
func createView() -> View {
return BlackView()
}
func createButton() -> Button {
return YellowButton()
}
}
class YellowViewBlackButtonFactory: ViewButtonFactory { // Concrete Creator
func createView() -> View {
return YellowView()
}
func createButton() -> Button {
return BlackButton()
}
}
클라이언트 객체 코드 예시
class ButtonBox {
private var viewButtonFacotry: ViewButtonFactory
private var button: Button
private var view: View
init(_ viewButtonFactory: ViewButtonFactory) {
self.viewButtonFacotry = viewButtonFactory
self.button = viewButtonFacotry.createButton()
self.view = viewButtonFacotry.createView()
}
func change(viewButtonFactory: ViewButtonFactory) {
self.viewButtonFacotry = viewButtonFactory
self.button = viewButtonFacotry.createButton()
self.view = viewButtonFacotry.createView()
}
func printComponents() {
print(self.view.getViewColor())
print(self.button.getButtonColor())
}
}
var buttonBox = ButtonBox(BlackViewYellowButtonFactory())
buttonBox.printComponents()
// Black View
// Yellow Button
print("\n## Change Factory ##\n")
buttonBox.change(YellowViewBlackButtonFactory())
buttonBox.printComponents()
// Yellow View
// Black Button
장점
팩토리 메서드 패턴처럼 개방-폐쇄 원칙을 준수할 수 있음과 동시에 팩토리 메서드 패턴이 해결하지 못하는 객체 조합 보장 문제를 해결할 수 있다.
단점
만약, Concrete Prouct의 종류에 변동이 생긴다면 기존의 Concrete Creator 코드를 수정해야 하는 상황이 발생할 수 있다.
'CS > 디자인 패턴' 카테고리의 다른 글
[GoF 디자인 패턴] - 싱글톤 패턴 (0) | 2024.12.02 |
---|---|
[GoF 디자인 패턴] - 프로토타입 패턴 (0) | 2024.11.29 |
[GoF 디자인 패턴] - 빌더 패턴 (0) | 2024.11.28 |
[GoF 디자인 패턴] - 팩토리 메서드 패턴 (1) | 2024.11.25 |
[GoF 디자인 패턴] - 디자인 패턴이란? (1) | 2024.11.22 |
댓글