Factory Method에 이어 Abstract Factory에 대해 알아보겠습니다.
이름처럼 두 패턴은 비슷한 점도 있지만 분명히 다른 점도 존재합니다.
서로 관련있는 객체를 만들어주는 패턴을 말합니다.
위에서도 언급했듯이 두 패턴은 결국 객체를 만들어 준다는 공통점이 존재하지만 Abstract Factory같은 경우 구체적으로 어떤 객체를 사용하는지에 대해 숨길 수 있습니다.
UML을 보면 Client는 구체적인 타입이 아닌 추상화된 프로토콜을 사용합니다.
지난번에 작성한 Factory Method를 가져오겠습니다.
패턴 적용 전
class Car {
var name: String
var color: String
var tire: Tire
init(name: String, color: String, tire: Tire) {
self.name = name
self.color = color
self.tire = tire
}
}
class Tire {
...
}
Car에 Tire라는 타입을 가지는 프로퍼티가 추가됐습니다.
그럼 기존에 만들어 놓은 Factory는 어떻게 변하는지 확인해 보겠습니다.
class K3Factory: Factory {
func makeCar(color: String) -> Car {
return K3(name: "K3", color: color, tire: Tire())
}
}
만약 제가 일반 Tire가 아닌 새로운 Tire를 만들어 사용하고 싶다면 어떻게 해야 할까요?
class NewTire {
...
}
class Car {
var name: String
var color: String
var tire: NewTire
init(name: String, color: String, tire: NewTire) {
self.name = name
self.color = color
self.tire = tire
}
}
class K3Factory: Factory {
func makeCar(color: String) -> Car {
return K3(name: "K3", color: color, tire: NewTire())
}
}
이처럼 기존의 코드를 변경해야 하는 불편함이 존재합니다.
패턴 적용
protocol CarPartFactory {
func createTire() -> Tire
}
class NormalTireFactory: CarPartFactory {
func createTire() -> Tire {
return NormalTire()
}
}
protocol Tire {
...
}
class NormalTire: Tire {
...
}
패턴 적용 전에는 Tire를 클래스로 만들었지만 프로토콜로 수정했습니다.
class K3Factory: Factory {
let partFactory: CarPartFactory
init(partFactory: CarPartFactory) {
self.partFactory = partFactory
}
func makeCar(color: String) -> Car {
return K3(name: "K3", color: color, tire: partFactory.createTire())
}
}
let normalFactory = NormalTireFactory()
let myCar = K3Factory(partFactory: normalFactory).orederCar(color: "White")
여기서는 각 부품에 대한 Abstract Factory를 결국 Factory에서 사용하기 때문에 위 코드처럼 작성했습니다.
여기서 NewTire를 사용하는 K3를 만들어 보겠습니다.
class NewTire: Tire {
...
}
class NewTireFactory: CarPartFactory {
func createTire() -> Tire {
return NewTire()
}
}
let newFactory = NewTireFactory()
let secondCar = K3Factory(partFactory: newFactory).orederCar(color: "Black")
K3Factory에 작성한 코드를 수정하지 않고 NewTire 사용하는 새로운 인스턴스를 생성할 수 있습니다.
이처럼 Abstract Factory를 사용하면 Client의 코드를 수정하지 않고 다른 타입을 가지고 있는 인스턴스를 생성할 수 있습니다.
해당 글은 인프런의 코딩으로 학습하는 GoF 디자인 패턴 강의와 블로그를 참고해 작성했습니다.
참고 블로그
Refactoring.Guru
⭐️ 부족하거나 잘못된 부분이 있다면 댓글은 언제나 환영입니다!! ⭐️