
정의
- 추상 팩토리 패턴 (Factory Method Pattern)이란 연관성이 있는 객체끼리 묶어 이를 추상화하고, 그 팩토리 객체 내에서 집합으로 묶은 객체 군을 다양한 형태로 구현화하는 생성 패턴이다.
- 예를 들어 Button, TextField, Switch라는 UI 객체가 있다고 가정해보자. 이 객체들을 우리는 애플 OS에서도 사용하고 싶고, Window OS에서도 사용하고 싶으며, Linux OS에서도 사용하고 싶을 경우, 이러한 복잡한 구조를 관리하기 용이하게 하기 위해 추상 팩토리 패턴이 사용된다고 보면 된다.
추상 팩토리 패턴 (Abstract Factory Pattern) 의 구조

- AbstractFactory ⇒
- 최상위 공장 프로토콜.
- 다양한 형태의 제품을 생성해내는 여러 메소드들을 추상화한다.
- ConcreteFactory ⇒
- 프로토콜이었던 AbstractFactory(추상 공장)를 실제 구체적인 객체로 옮기는 영역.
- “최상위 공장에 존재하는 여러 객체를 “여러 형태의 제품군 (애플 OS, Window OS, Rinux OS)”으로 나누어 구체화”시킬 수 있다.
- AbstractProduct ⇒
- Abstract Factory에 들어갈 하나 하나의 객체 프로토콜 타입.
- Abstract Product는 Abstract Factory 내부의 메소드의 리턴 타입이 된다. ⭐️
- ConcreteProduct ⇒
- 프로토콜이었던 AbstractProduct(추상화 객체)를 실제 구체적인 객체로 옮기는 영역.
추상 팩토리 패턴과 팩토리 메소드 패턴의 공통점과 차이점
- 공통점
- 객체 생성 과정을 “팩토리 객체를 통해 추상화”한다.
- Client 단에서는 직접적인 객체 타입이 아닌 추상적인 객체 타입 인스턴스를 팩토리 객체로부터 받아오므로 의존성을 떨어뜨림과 동시에 결합도를 크게 줄일 수 있다.
- 차이점
- 추상 팩토리 패턴
- 한 팩토리 객체(프로토콜) 내부에 서로 연관된 “여러 종류의 객체 생성”을 지원한다.
- 모니터, 마우스, 키보드를 묶은 전자 제품군이 있는데 그 제품군을 또 애플 제품군이냐, 삼성 제품군이냐, 로지텍 제품군이냐로 나눌 경우, 이 복잡한 구조를 관리하기 용이하게 만드는 것이 주 목적.
- 팩토리 메소드 패턴
- 한 팩토리 객체(프로토콜) 내부에는 “하나의 객체 생성”만 지원한다.
- 팩토리 객체 내에서 객체 생성 인스턴스를 프로토콜 타입으로 지원하여 Client와 실제 객체와의 결합도를 낮추는 것이 주 목적.
Swift로 추상 팩토리 패턴 적용 과정 예시
- 신용카드, 페이팔 등으로 결제 처리 방법이 다를 경우를 예시로 추상 팩토리 패턴을 적용해 볼 것이다. 우선 객체 내부의 로직을 표현하기 위한 Abstract Product 프로토콜을 생성한다.
protocol PaymentProcessor {
func processPayment()
}
protocol PaymentValidator {
func validatePaymentDetails() -> Bool
}
- 그 후, Abstract Product 프로토콜을 채택한 구체적인 객체들을 생성하여 내부를 구현한다.
class CreditCardProcessor: PaymentProcessor {
func processPayment() {
}
}
class CreditCardValidator: PaymentValidator {
func validatePaymentDetails() -> Bool {
return true
}
}
class PayPalProcessor: PaymentProcessor {
func processPayment() {
}
}
class PayPalValidator: PaymentValidator {
func validatePaymentDetails() -> Bool {
return true
}
}
- Abstract Factory는 Abstract Product를 리턴 타입으로 가지는 메소드를 소유하고 있다. 추상 팩토리 패턴에서 Abstract Factory는 Abstract Product를 생성해내는 메소드를 “여러 개 보유할 수 있다.“
protocol PaymentFactory {
func createPaymentProcessor() -> PaymentProcessor
func createPaymentValidator() -> PaymentValidator
}
- Abstract Factory 프로토콜을 채택하여 구체적인 공장 객체 (Concrete Factory)를 여러 종류로 만들어낸다. (CreditCardFactory, PaypalFactory etc.)
class CreditCardFactory: PaymentFactory {
func createPaymentProcessor() -> PaymentProcessor {
return CreditCardProcessor()
}
func createPaymentValidator() -> PaymentValidator {
return CreditCardValidator()
}
}
class PayPalFactory: PaymentFactory {
func createPaymentProcessor() -> PaymentProcessor {
return PayPalProcessor()
}
func createPaymentValidator() -> PaymentValidator {
return PayPalValidator()
}
}
- Client에서는 Abstract Factory 프로토콜을 타입으로 하는 상수를 선언하고 생성자로 초기화한다. 이 상수에 Abstract Factory 프로토콜을 타입으로 갖는 모든 객체가 할당될 수 있다.
class PaymentSystem {
private let factory: PaymentFactory
init(factory: PaymentFactory) {
self.factory = factory
}
func processPayment() {
let validator = factory.createPaymentValidator()
if validator.validatePaymentDetails() {
let processor = factory.createPaymentProcessor()
processor.processPayment()
} else {
print("결제 처리가 실패하였습니다")
}
}
}
class Client {
let creditCardPaymentSystem = PaymentSystem(factory: CreditCardFactory())
let payPalPaymentSystem = PaymentSystem(factory: PayPalFactory())
func creditCardProcessPayment() {
creditCardPaymentSystem.processPayment()
}
func payPalProcessPayment() {
payPalPaymentSystem.processPayment()
}
}
패턴 사용 시기
- 여러 가지 객체들을 여러 종류군으로 나누는 복잡한 구조를 편리하게 관리하고자 할 때 사용된다.
- Button, TextField, Switch라는 UI 객체가 있을 경우, 이 객체들을 우리는 애플 OS에서도 사용하고 싶고, Window OS에서도 사용하고 싶으며, Linux OS에서도 사용하고 싶을 경우. (복잡한 구조를 관리)
패턴의 장점
- SRP ⇒ 여러 가지 객체들이 모두 자신의 책임에만 충실하다. 즉, 책임이 단일하다.
- OCP ⇒ Abstract Factory 프로토콜을 통해 기존 코드를 수정하지 않고도 새로운 유형의 Concrete Factory를 계속해서 생성할 수 있으므로 OCP를 만족한다.
- 여러 객체가 다양한 형태로 나뉘어져 있는 복잡한 구조를 쉽게 관리할 수 있다.
패턴의 단점
- 새로운 제품군이 추가될 때마다 팩토리 객체들을 추가하여 내부를 모두 구현해주어야 하기 때문에 코드의 복잡성이 증가한다. (팩토리 관련 패턴의 공통적인 문제점이다.)
- 새로운 종류의 객체를 추가하면 (Abstract Factory 내부에 새로운 메소드를 추가) 관련 Concrete Factory 객체를 모두 수정해주어야 하기 때문에 새로운 종류의 객체를 추가하기는 까다롭다.
참고 문헌
최근 개인적으로 추상 팩토리에 대한 내용을 읽으며,
이전에 읽었던 마리골드님의 메서드 팩토리와는 무슨 차이인 지 고민하던 차인데 반가운 포스팅입니다!
제가 추상 팩토리에 대한 내용을 접한 것은 '클린 아키텍처' 책의 DIP(의존성 역전 원칙)에 대해 다루는 글 속에서 입니다.
포스팅을 읽으며 제가 가진 추상 팩토리 개념을 점검하고, 이전 메서드 팩토리와의 차이점도 명확히 할 수 있었습니다.
감사히 잘 읽었습니다!