디자인 패턴/구조 패턴

[디자인 패턴] 데코레이터(Decorater) 패턴이란

Jㅐ둥이 2022. 8. 29. 09:30
반응형

오늘 공부할 패턴은 디자인 패턴은 데코레이터 패턴입니다.

 

1. 데코레이터 패턴이란

데코레이터 패턴은 서브 클래스를 추가하는 것보다 간단하게 기능을 추가할 수 있어서 한번씩 활용하는 패턴입니다. 브릿지 패턴과 어답터 패턴을 활용한 느낌이라고 이해하시면 될 것 같습니다. 그래서 Wrapper 함수 혹은 클래스를 구현하면서 알게 모르게 데코레이터 패턴을 적용하셨을지도 모릅니다.

 

한번 예시를 살펴볼까요?

 

2. 활용하기 좋은 순간

  • 추상화 시키기 애매한 기능을 추가적으로 개발해야 할 때
  • 기능 추가를 위해서 수정해야 하는 서브클래스가 너무 많아지고 있을 때

 

3. 예시

이번에도 CarInterface를 활용해볼게요! 원래는 차에 기능이 추가되면 모든 구현체 클래스에 해당 메소드를 추가했는데 이번에는 데코레이터 패턴을 활용해서 구현해보겠습니다. 구체적으로 파헤쳐볼까요?

 

CarInterface를 상속하는 K3, K5, K8 클래스가 있습니다. 아니 그런데 자동차 브레이크의 성능이 좋아져서 break 메소드를 호출하면 speed가 바로 0이 되어야 합니다. 이런 K3, K5, K8 클래스를 모두 고쳐야 할까요?

데코레이터 패턴을 이용해서 해결한 예시를 봐주시죠!

 

Car 객체를 생성한 뒤, GoodBreakCarDecorator의 생성자의 인자로 넘겨주기만 하면 끝나죠? 매우 간단한 방법으로 기능을 수정할 수 있었습니다.

 

하지만 기능 수정을 위해서 무분별하게 CarDecorator를 추가하다보면 관리도 어려워지고, Decorator 클래스들이 어떤 영향을 끼치게 될지 예측하기 어려워질 수 있습니다. 패턴은 한번 적용했다고 끝이 아닙니다. 계속해서 좋은 해결책을 고민해야 해요!

## car.py
from abc import ABCMeta, abstractmethod

class CarInterface(metaclass=ABCMeta):
    def __init__(self):
        self.speed = 0
        
    @abstractmethod
    def break(self):
    	pass
        
    @abstractmethod
    def accelerate(self):
    	pass

## car_decorator.py
from abc import ABCMeta, abstractmethod
class CarDecorator(metaclass=ABCMeta):
    def __init__(self, car: CarInterface):
        self.car = car
        
    @abstractmethod
    def break(self):
        pass
        
    @abstractmethod
    def accelerate(self):
    	pass
        
## good_break_car_decorator.py
class GoodBreakCarDecorator(CarDecorator):
    def break(self):
        self.car.speed = 0
    
    def accelerate(self):
        self.car.accelrate()

## k3.py
class K3(CarInterface):
    def break(self):
    	self.speed -= 1
    
    def acclerate(self):
    	self.speed += 1

## k5.py
class K5(CarInterface):
    def break(self):
    	self.speed -= 2
    
    def acclerate(self):
    	self.speed += 2

## k8.py
class K8(CarInterface):
    def break(self):
    	self.speed -= 3
    
    def acclerate(self):
    	self.speed += 3

if __name__ == "__main__":
    car = GoodBreakCarDecorator(K3())
    car.break()
반응형