본문 바로가기
Programming/OOP

[Design Pattern] Factory Method Pattern, 팩토리 메서드 패턴

by TinKerBellBass 2022. 4. 25.
728x90
반응형

DIP(Dependency Inversion Principle), 의존성 역전 원칙

변경에 강한 설계를 하기 위한 방법 중 잘 알려진 SOLID 원칙의 하나로 의존 흐름을 역전시키는 방법으로,

육각형 아키텍처의 포트-어댑터도 이 방법으로 구현할 수 있다.

UploadService 의 upload 메서드에서 S3Storage 인스턴스를 생성하고 있기 때문에

UploadService 는 S3Storage 에 의존하고 있으며 강하게 결합하고 있다.

S3Storage 는 물리적으로 파일을 업로드하는 인프라적인 영역이므로 포트-어댑터에서 외부 영역으로 볼 수 있는데

서비스 로직이라는 핵심 영역이 외부 영역에 의존하고 있는 형태이다.

 

이 둘의 관계를 느슨하게 만들기 위해서 의존성 역전이라는 방법을 사용한다.

UploadService 에서 파일 업로드를 위한 인터페이스를 만들어주고(포트)

S3Storage (어댑터)가 그 인터페이스에 따라 구현하게 만들면 된다.

 

정리하면, 변경이 예상되는 부분을 추상화시켜 인터페이스를 만들고,

그 인터페이스에 따라 구상 클래스를 만드는 것이다. 

인터페이스를 두고 S3Storage 가 인터페이스에 맞춰 구현하도록 변경되었고 화살표 방향도 뒤집혔다.

UploadService 는 이제 어떤 구상 클래스가 파일을 업로드하는지 모르며

UploadService 를 사용하는 쪽에서 구상 클래스를 결정하게 되었다.

인프라 쪽에 변경이 생겨도  UploadService 는 알아차리지 못하며 평소 하던 대로 행동하면 되는 것이다.

 

 

Factory Method Pattern

공장에서 효율적으로 제품을 만들기 위한 것이 팩토리 메서드 패턴으로

여기서 공장은 인스턴스를 생성하는 곳이고, 제품은 생성되는 인스턴스이다.

여기서는 공장에 집중하고 제품은 다음 추상 팩토리 패턴에서 구현할 것이다.

 

팩토리 클래스라고 하면 분기문(보통 스위치)으로 필요한 인스턴트를 생성해서 반환하는 클래스가 생각난다.

이것은 아주 작은 팩토리 패턴이라고 볼 수 있는데, 

팩토리 메서드 패턴은 조금 더 나아가서 공장을 추상화 해서 다양한 공장을 구상 클래스로 만들고,

공장 구상 클래스에서 필요한 제품을 생산한다.

책에서 예를 들고 있는 것을 대충 생각나는 대로 적어보면 아래와 같다.

추상 공장 피자 스토어
구상 공장 1 뉴욕 피자 스토어
구상 공장 1 의 제품 뉴욕 치즈 피자, 뉴욕 쉬림프 피자....
구상 공장 2 시카고 피자 스토어
구상 공장 2 의 제품 시카고 불고기 피자, 시카고 불닭 피자...

추상 공장에서는 팩토리 메서드를 정의 해서, 구상 공장에서 구현하도록 강제한다.

제품을 생산하는 것을 구상 클래스에게 위임하는 것이다.

 

Factory Method Pattern Class Diagram

Factory 라고 이름 붙은 것들이 공장 클래스(Creator), Vehicle 과 Vehicle 의 확장 클래스가 제품(Product) 클래스이다.

추상 공장인 VehicleFactory 를 구현한 SuperVehicleFactory, UltraVehicleFactory 구상 공장에서

VehicleType 에 따라 Vehicle 인스턴스가 만들어진다.

제품인 Vehicle 은 이름, 엔진, 타이어를 필드로 가지며, 조립 메서드와 선적 메서드를 가지며 추상 팩토리 패턴으로 변경할 예정이다.

팩토리 메서드 패턴의 핵심은 공장 쪽에 있으며 공장을 추상화하여 구상 클래스에서 공장별로 제품을 생성한다는 것이다.

전체 소스는 https://github.com/Jongwon-Hyun/design_pattern

 

공장 클래스와 제품 클래스의 의존성 역전

제품인 SuperBus, SuperTruck, UltraBus, UltraTruck 을 공장 클래스에서 직접 사용하면

공장 클래스는 제품 클래스에 아주 강하게 결합되어 변경 사항이 발생했을 때 수정하기 힘들어진다.

Vehicle 이라는 추상화된 제품이 사라지는 순간

VehicleFactory 의 createVehicle 메서드의 반환 값부터 머리 아파진다.

아래와 같은 메서드들을 만들어야 할 것이고, 제품인 Vehicle 이 늘어날 때마다 메서드를 추가해야 할 것이다.

그리고 팩토리 메서드 패턴을 쓰는 의미가 없어져 공장 클래스는 구상 클래스 하나만 있으면 될 것이고,

시간이 흐를수록 유지보수가 힘들어지는 스파게티 코드가 되어갈 것이다.

SuperBus createSuperBus(){...}
SuperTruck createSuperTruck(){...}
UltraBus createUltraBus(){...}
UltraTruck createUltraTruck(){...}

단순히 제품을 추상화 해서 의존성을 역전시켰을 뿐인데 이 문제가 사라진다.

OOP, 디자인 패턴의 핵심은 역시 추상화와 다형성이 아닐까 생각해 본다.

728x90
반응형

댓글