디자인 패턴 중 Factory Method 패턴에 대해 설명합니다.
개념
Factory Method 패턴은 슈퍼 클래스에서 비즈니스 로직에 사용되는 객체의 객체 생성 인터페이스를 제공하고, 서브 클래스에서 생성할 객체의 타입을 결정하는 생성 패턴입니다. 다음과 같은 장점이 있습니다.
- Open-Closed Principle: 객체 생성자 호출을 비즈니스 로직과 분리하여 객체의 타입이 늘어나도 비즈니스 로직이 수정될 필요가 없습니다. 클래스 확장을 통해 해결합니다.
- Single Responsibility Principle: 객체 생성에 대한 책임을 분리하여 비즈니스 로직의 과도한 책임을 분산합니다.
- Dependency Inversion Principle: 구체적인 구현 객체에 의존하지 않고 인터페이스에 의존합니다.
자세히 살펴보겠습니다.
Factory Method는 비즈니스 로직과 객체 생성자 호출을 담당하는 Creator와 비즈니스 로직에 사용되는 객체인 Product로 나뉩니다.
Creator
Creator는 비즈니스 로직이 포함된 클래스입니다. 비즈니스 로직에서 Product 객체를 생성하고 사용하는데 객체 생성자 호출을 분리하여 하위 클래스에서 어떤 Product 객체를 생성할 것인지 선택하도록 합니다. Creator 로직은 Product가 변화하거나 새로운 구현 클래스가 생겨나더라도 수정되지 않습니다.
Product
Product는 클라이언트 코드에서 Product의 구체적인 구현에 의존하지 않도록 인터페이스로 만듭니다. 그리고 실질적인 로직이 구현되어 있는 구현 클래스들이 존재합니다. 이들은 Creator 하위클래스에서 생성됩니다.
적용 예시
배달의 민족 같은 딜리버리 서비스 앱을 운영 중이라고 가정합니다.
DeliveryService에는 Motocycle 객체를 생성하여 사용하는 deliver 메소드가 존재합니다. 즉, 비즈니스 로직 내에서 어떠한 객체를 생성해서 사용하고 있었습니다.
개발 당시는 운송수단을 Motocycle만 고려하였는데 운송수단에 대한 새로운 요구사항이 등장했습니다. Bicycle이 추가되어야 합니다. 그럼 다음과 같이 코드를 작성할 수 있습니다.
class DeliveryService:
...
def deliver(self, vehicle_type):
...
if vehicle_type == "bicycle":
vehicle = Bicycle()
else:
vehicle = Motocycle()
vehicle.run()
...
Open-Closed Principle을 어기게 되었습니다. 운송수단이 추가될 때마다 deliver 메소드에 조건문이 계속 추가될 것입니다. 또, deliver 메소드는 vehicle의 타입에 따라 생성과 사용이라는 과도한 책임이 부과되었고 Bicycle, Motocycle이라는 구체적인 구현에 의존하고 있습니다.
Factory Method 패턴을 적용하면 이를 해결할 수 있습니다.
class Vehicle(abc.ABC):
@abc.abstractmethod
def run(self): ...
class Motorcyle(Vehicle):
def run(self): ...
class Bicycle(Vehicle):
def run(self): ...
class AbstractDeliveryService(abc.ABC):
...
def deliver(self):
...
vehicle = self.create_vehicle()
vehicle.run()
...
@abc.abstractmethod
def create_vehicle(self) -> Vehicle:
return Vehicle()
class MotorcyleDeliveryService(AbstractDeliveryService):
def create_vehicle(self) -> Vehicle:
return Motorcyle()
class BicycleDeliveryService(AbstractDeliveryService):
def create_vehicle(self) -> Vehicle:
return Bicycle()
DeliveryService 슈퍼클래스의 로직중 생성자 호출을 create_vehicle 메소드로 분리하였습니다. 이제 새로운 운송수단이 생겨나도 DeliveryService의 하위클래스를 작성하여 create_vehicle 메소드만 오버라이드하면 됩니다.
참조
https://refactoring.guru/design-patterns/factory-method
'객체 지향 > 디자인 패턴' 카테고리의 다른 글
디자인 패턴 - Adapter (0) | 2023.10.12 |
---|---|
디자인 패턴 - Singleton (0) | 2023.10.11 |
디자인 패턴 - Prototype (0) | 2023.10.09 |
디자인 패턴 - Builder (0) | 2023.10.09 |
디자인 패턴 - Abstact Factory (0) | 2023.10.05 |