데코레이터 패턴이란?

객체의 결합을 통해, 기능을 동적으로 확장할 수 있게 해주는 패턴

서브 클래스의 생성 대신 데코레이터를 통해 클래스의 기능을 확장하여 제공

구조

structure.png

  • Component
    클라이언트가 사용하는 객체
    기본 기능과 추가기능의 집합체
  • Decorator
    추가적으로 제공할 기능의 공통 인터페이스
  • ConcreateComponent
    기본 기능을 구현할 객체
  • ConcreateDecorator
    추가적으로 제공의 개별적인 기능의 구현체

언제 사용할까?

기능을 추가할 객체를 수정하지 않고 새로운 기능이나 책임을 추가할 때

조합으로 재활용하여 다른 곳에도 사용하고 싶을 때

서브 클래스를 만드는 것이 비효율적일 때

추가적으로 고려할점

  • Component는 장식을 추가할 베이스가 되는 역할이므로 작고 가볍게 정의하도록 한다.

    • 가급적 인터페이스만을 정의한다.
    • 무언가 저장하는 변수는 정의하지 않는다. (상속받는 여러 Decorator도 같이 복잡하고 무거워진다).
    • 저장할 것이 있다면 서브클래스에서 하자.
  • 상속 구조를 통해 DecoratorComponent가 같은 인터페이스를 갖게 해야 한다.

    • 투과적 인터페이스: Decorator로 계속해서 감싸도 Component의 메소드는 계속 사용할 수 있다.
  • 코드를 수정하지 않고도 준비된 Decorator을 조합해 기능을 추가할 수 있도록 생각해서 구현한다.

  • 비슷한 성질의 작은 클래스가 많이 만들어질 수 있다는 단점을 고려한다. 구현하려는 내용이 객체의 겉을 변경하려는 것인지, 속을 변경하려는 것인지 생각해 보자.

    • 속을 변경하려는 것이라면 strategy-pattern을 선택하는 것이 더 적절할 수 있다.
  • 데코레이터 패턴으로 구현한 다음, 사용이 까다롭게 느껴지거나 자주 쓰는 조합이 있다면 다음 패턴을 사용해 제공하는 것을 고려해 보자.

    • builder-pattern
    • factory-pattern
    • static-factory-method-pattern
  • Decorator가 다른 Decorator에 대해 알아야 할 필요가 있다면, 데코레이터 패턴의 사용 의도와 어긋나는 작업일 수 있다.

  • 재귀적으로 기능을 갖게 하는 방법 외에도, Decorator를 추가할 때마다 얻은 아이템을 List로 관리하는 방법도 있다.


참조