디자인 패턴 중 Decorator 패턴에 대해 설명합니다.
개념
래퍼 객체 안에 객체를 두어 기능을 확장하는 구조 패턴입니다. 특정 조건에 따라 객체의 기능이 확장되어야 할 때 객체를 래핑하고 래퍼 객체와 타겟 객체가 동일한 인터페이스로 제공되어 클라이언트에서는 이를 동일하게 취급할 수 있습니다. 동적으로 객체 기능 확장이 필요할 때 사용합니다.
- Component: 래퍼와 타겟 객체의 공통 인터페이스입니다. 타겟 객체의 메소드를 정의하여 래퍼 객체도 동일한 메소드를 호출할 수 있도록 합니다.
- ConcreteComponent: 래핑되는 타겟 객체입니다.
- BaseDecorator: 타겟 객체를 래핑 하는 래퍼 객체의 Abstract class입니다. wrappee로 타겟 객체를 저장하고 특정 메소드가 호출되었을 때 wrappee의 메소드를 호출합니다.
- ConcreteDecorator: BaseDecorator를 상속받아 wrapper의 기능을 강화하는 클래스입니다. wrappee의 메소드를 호출 전/후에 추가적인 행동을 하여 기능을 강화하게 됩니다.
다음과 같은 장점이 있습니다
- 런타임에 객체의 기능을 확장합니다.
- Single Responsibility Principle: 데코레이터는 특정 기능에 대한 책임만 담당합니다.
- Open-Closed Principle: 객체 수정 없이 데코레이터를 추가하여 기능을 확장할 수 있습니다.
- 여러 데코레이터를 중첩하여 객체의 기능을 확장할 수 있습니다.
- 상속을 남용하여 필요 이상 많은 클래스가 추가되는 클래스 폭발(class explosion)을 막을 수 있습니다
적용 예시
커피 주문 애플리케이션을 개발중이라고 가정합니다. 커피에 휘핑크림, 자바칩, 시나몬 가루등 다양한 옵션 추가를 구현할 예정입니다. 커피 옵션을 추가하기 위해 데코레이터 패턴을 사용할 수 있습니다.
from abc import ABC, abstractmethod
class Beverage(ABC):
@abstractmethod
def add(self): ...
class BeseDecorator(Beverage):
def __init__(self, wrappee: Beverage) -> None:
self._wrappee = wrappee
def add(self):
self._wrappee.add()
class WhippingCreamDecorator(BeseDecorator):
def add(self):
super().add()
print("add whippingcream")
class JavaChipDecorator(BeseDecorator):
def add(self):
super().add()
print("add javachip")
class Coffee(Beverage):
def add(self):
print("add coffee")
c = Coffee()
c = WhippingCreamDecorator(c)
c = JavaChipDecorator(c)
c.add()
데코레이터 패턴을 사용하여 Coffee 객체에 휘핑크림, 자바칩 같은 기능을 강화하기 위해 래퍼 객체들로 감쌉니다. 추가할 만큼 추가한 후 add 메소드를 호출하면 모든 wrappee의 add 메소드가 호출됩니다.
>>>>> add coffee
add whippingcream
add javachip
참조
'객체 지향 > 디자인 패턴' 카테고리의 다른 글
디자인 패턴 - Flyweight (0) | 2023.10.28 |
---|---|
디자인 패턴 - Facade (0) | 2023.10.28 |
디자인 패턴 - Composite (0) | 2023.10.22 |
디자인 패턴 - Bridge (0) | 2023.10.21 |
디자인 패턴 - Adapter (0) | 2023.10.12 |