쉽게 생각해봅시다. 팩토리를 공장이라고 부르죠?
공장에다가 물건을 주문했다고 생각해 봅시다.
공장한테 어떤걸 달라고 명령할수는 있지만, 우리는 공장에서 어떻게 만들어졌는지, 무엇인지는 모릅니다.
Interface로 감싸져 있는 상자만 받았을 뿐입니다.
팩토리 메서드 패턴이란, 서브 클래스(Factory)에서 어떤 클래스를 만들지 결정하게 함으로써 객체생성을 캡슐화하는 패턴입니다.
즉, 하나의 Interface가 있고 그를 구현한 Concrete class들, 어떤 Concrete class 인지를 결정하는 Factory 클래스가 존재할 뿐입니다.
아래에 코드로 예시를 들어볼까요?
위의 그림과 같이 Delivery라는 운송에 대한 Interface
가 있습니다.
그리고 Road()와 Air() 라는 Class
는 가는 방법을 정하는 클래스입니다.
Factory가 사용되지 않는 코드를 만들어 봅시다.
fun transfer() {
// 어디로 보낼지 결정
val deliveryType: DeliveryType = choiceDeliveryType()
val transport = if (deliveryType == DeliveryType.AIR) {
Air()
} else if (deliveryType == DeliveryType.ROAD) {
Truck()
}
transprot.send()
}
위의 코드는 choiceDeliveryType
으로부터 운송방법이 정해지면, Concrete Class를 만들어서 호출하고 있습니다.
여기서 문제는 Air(), Truck(), Boat()를 transfer() 함수가 알고있어야 한다는거에요.
그리고 여기서 deliveryType이 더 늘어난다면 transfer() 함수는 변경이 일어나야 되겠죠?
fun transfer() {
// 어디로 보낼지 결정
val deliveryType: DeliveryType = choiceDeliveryType()
val transport = if (deliveryType == DeliveryType.AIR) {
Air()
} else if (deliveryType == DeliveryType.ROAD) {
Truck()
} else if(deleiveryType == DeliveryType.BOAT){
Boat()
}
transprot.send()
}
그렇다면 한번 Factory패턴을 적용해볼까요?
팩토리패턴은 Concrete Class
를 선택하는 부분을 캡슐화 시킴으로써 이루어집니다.
fun transfer() {
//인수로 넘겨준 타입에 따라 구상객체가 결정되지만 함수는 구상객체가 뭔지모른다.
val transport = choiceTransPort(DeliveryType.BOAT)
transport.send()
}
//여기서 타입을 정해준다.
fun choiceTransPort(type: DeliveryType): Transport {
if (type == DeliveryType.AIR) {
return Air()
} else if (type == DeliveryType.ROAD) {
return Truck()
} else if (type == DeliveryType.BOAT) {
return Boat()
}
return Boat()
}
위의 코드는 더이상 transfer()
함수가 Transport
의 Concrete Class(구현체) 모르고 있어도 됩니다.
아래의 choiceTransPort()에게 위임이 되었으니까요.
이제 이러한 장점을 확인해 볼까요?
장점
디자인 패턴 코틀린 파트 1
헤드 퍼스트 디자인
자바 팩토리 메서드 패턴
코틀린 팩토리 메서드 패턴
팩토리 메서드 패턴 - 코틀린 월드