1. Abstract Product: product 패밀리를 구성하는 개별 연관 제품들의 집합에 대한 인터페이스를 선언합니다.
2. Concrete Product: abstract product들의 다양한 구현입니다.
3. Abstract Factory: 인터페이스는 각각의 abstract products를 생성하기 위한 여러 메서드들의 집합을 선언합니다.
4. Concrete Factory: abstract factory의 생성 메서드들을 구현합니다.
5. Client: Client는 추상화된 인터페이스만을 이용하여 product를 받기 때문에, concrete product, factory에 대해서는 모릅니다.
위와 같이 GUI를 구성하는 예제입니다.
첫째로 abstract factory부분을 만들어줍니다.
protocol GUIAbstractFactory {
func createButton() -> Button
func createCheckbox() -> Checkbox
}
protocol Button {
func paint()
}
protocol Checkbox {
func paint()
}
윈도우에서 사용할 것들을 만든다면?
class WinFactory: GUIAbstractFactory {
func createButton() -> Button {
return WinButton()
}
func createCheckbox() -> Checkbox {
return WinCheckbox()
}
}
class WinButton: Button {
func paint() {
print("윈도우 스타일로 버튼 렌더링")
}
}
class WinCheckbox: Checkbox {
func paint() {
print("윈도우 스타일로 체크박스 렌더링")
}
}
같은 방법으로 맥에서 사용하는 것을 구현하면
class MacFactory: GUIAbstractFactory {
func createButton() -> Button {
return MacButton()
}
func createCheckbox() -> Checkbox {
return MacCheckbox()
}
}
class MacButton: Button {
func paint() {
print("맥 스타일로 버튼 렌더링")
}
}
class MacCheckbox: Checkbox {
func paint() {
print("맥 스타일로 체크박스 렌더링")
}
}
비슷하게 다른 OS에서 사용하는 것을 만들 수 있습니다.
위와 같이 직접 OS를 신경쓰지 않도록 GUIFactory 객체를 하나 만들어 보겠습니다.
class GUIFactory {
public static var factory: GUIAbstractFactory? {
#if os(macOS)
return MacFactory()
#elseif os(Windows)
return WinFactory()
#elseif os(iOS)
return iOSFactory()
#else
return nil
#endif
}
}
이렇게 다양한 요소 별로 객체의 집합을 생성해야 할 때 추상 팩토리 패턴이 유용한 것을 볼 수 있습니다.