// Product - **“객체 내부의 로직을 표현”**하기 위해 만들어진
// 추상적인 프로토콜 타입
protocol PaymentProcess {
func process()
}
// Concrete Products - 객체 내부의 로직을 실제로 표현하는 영역.
// 즉, 결제 처리 방법을 실제 로직으로 구현하는 영역이라고 보면 된다.
class CreditCard: PaymentProcess {
func process() {
// 신용카드에서 결제를 처리하는 로직을 입력한다.
}
}
class Paypal: PaymentProcess {
func process() {
// 페이팔에서 결제를 처리하는 로직을 입력한다.
}
}
class Crypto: PaymentProcess {
func process() {
// 암호화폐에서 결제를 처리하는 로직을 입력한다.
}
}
// Creator - 객체(제품)의 인스턴스를 찍어내는 추상 공장.
// 즉, CreditCard, Paypal, Crypto 등의 인스턴스를
// 직접 찍어내는 것이 아니라 (CreditCard(), Paypal(), Crypto())
// Creator라는 추상 공장의 메소드로 하여금 Product 프로토콜 타입을 리턴하도록 하여
// Client가 특정 객체와의 의존성이 크게 줄어들게끔 만든다. ⭐️⭐️
// 다시 말해, 인스턴스를 직접 생성하는 것이 아닌 추상 공장을 통해서 간접적으로 인스턴스를 얻어낸다는 것이다.
protocol PaymentFactory {
func createPaymentProcess() -> PaymentProcess
}
// Concrete Creators - 프로토콜이었던 추상 공장을 실제 구체적인 객체로 옮기는 영역.
// 추후, Client는 객체 인스턴스를 직접 찍어내는 것이 아닌
// Concrete Creators를 통해서 간접적으로 인스턴스를 얻어온다.
// 리턴 타입이 Product 프로토콜 타입이므로 Client와 특정 객체와의 의존성이 크게 줄어든다.
class CreditCardFactory: PaymentFactory {
func createPaymentProcess() -> PaymentProcess {
return CreditCard()
}
}
class PaypalFactory: PaymentFactory {
func createPaymentProcess() -> PaymentProcess {
return Paypal()
}
}
class CryptoFactory: PaymentFactory {
func createPaymentProcess() -> PaymentProcess {
return Crypto()
}
}
// Client
class Client {
// Concrete Creators로부터 간접적으로 인스턴스를 얻어옴 ⭐️
let creditCardFactory = CreditCardFactory()
let paypalFactory = PaypalFactory()
let cryptoFactory = CryptoFactory()
func process(using payment: PaymentFactory) {
let paymentProcess = payment.createPaymentProcess()
paymentProcess.process()
}
}
let client = Client()
client.process(using: client.creditCardFactory) // 신용카드의 결제 방식을 실행한다.
Client가 Factory들을 프로퍼티로 가지고 있으면 이미 강하게 결합되어 있는 것으로 볼 수 있지 않나요?
만약 '계좌이체'라는 결제 방식이 생기면 Client 클래스에 해당 팩토리를 프로퍼티로 추가해 줘야 하는 거 아닌가 싶어서요
팩토리패턴! swift로 상세히 풀어주셔서 너무나 재미있게 읽었습니다.
과거에 공장
이라는 표현이 가지는 느낌(객체생성 책임 전가?)에 꽂혀서 해당 패턴의 목적을 반복 생성! 이라 마음대로 풀이하고 혼란스러웠던 적이 있습니다.
예시들어주신 다양한 공장들을 일반적으로 처리하는 코드를 보니 팩토리 패턴의 특성을 편하게 이해할 수 있었던 것 같습니다.
func process(using payment: PaymentFactory) {
let paymentProcess = payment.createPaymentProcess()
paymentProcess.process()
}
PaymentFactory를 통해 공장 객체에 접근하니 실제 구현을 몰라도 된다는 구절의 의미가 잘 와닿았습니다.
새로운 공장이 추가된다 한들 변하지 않는 코드이니 변경이 수정을 요하지 않아 자유롭구요!
^새로운 인스턴스가 필요하다면, 수정하지 않고 추가하면 된다^
는 문장 또한 많은 이해를 도왔습니다. 필요한 상황에 적절히 사용하겠습니다! 감사히 잘 읽었습니다!
제가 이전프로젝트에서 swinject로 container를 사용할지 아니면 factory를 사용할지 고민을 했었는데 라이브러리대신 factory를 사용하는게 좀더 끌려서 팩토리패턴을 사용했었는데 이렇게하니까 MVVM에서 데이터를 전달할떄 조금 까다롭더라고요 물론 이부분에서 swinject도 자유로울순없겠지만 편한대신 데이터전달이 조금 불편하다?(저는 이중 delegate을 썼던기억이나에요)라는 생각이드는 패턴입니다 개인적으로는 ㅎㅎ