Design Pattern

[디자인 패턴] 데코레이터 패턴 (Decorator Pattern)

꾸준함. 2024. 6. 29. 12:18

데코레이터 패턴

  • 객체의 기능을 동적으로 확장할 수 있게 해주는 구조적인 디자인 패턴
  • 상속이 아닌 위임을 통해 런타임에 부가 기능을 추가하는 것이 가능해짐

 

https://www.geeksforgeeks.org/decorator-design-pattern-in-java-with-example/

 

주요 구성 요소

 

1. Component

  • 데코레이터와 실제 객체의 공통 인터페이스 혹은  추상 클래스
  • ex) Shape 인터페이스

 

2. ConcreteComponent

  • 기본 기능을 구현하는 실제 객체
  • ex) Circle, Rectangle 클래스

 

3. Decorator

  • Component 인터페이스를 구현하거나 상속받는 추상 클래스
  • 해당 클래스는 실제 객체에 대한 참조를 포함(Dependecy Injection)하며, Component 인터페이스의 메서드를 위임(delegation)
  • ex) ShapeDecorator

 

4. ConcreteDecorator

  • Decorator 클래스를 확장하여 추가적인 기능을 구현한 클래스
  • 해당 클래스는 Component의 메서드를 호출하여 기본 기능을 유지한 상태로 추가적인 기능을 구현
  • ex) RedShapeDecorator

 

데코레이터 패턴 vs 컴포짓 패턴

  • 객체 구조를 다루는 디자인 패턴이라는 점에서 컴포짓 패턴과 유사하지만 목적과 사용 방식에 따라 차이점 존재

 

    데코레이터 패턴 컴포짓 패턴
유사한 점

1. 두 패턴 모두 객체의 구조를 정의하고 조작하는 것에 중점을 둠

2. 두 패턴 모두 재귀적으로 객체를 구성하는 방식으로 동작하기 때문에 트리 구조를 형성

3. 새로운 기능을 추가하거나 변경하는 데 있어 매우 유연하며 객체를 동적으로 구성할 수 있어 상속을 통한 확장보다 유연함


4. 두 패턴 모두 공통 인터페이스를 사용하여 객체를 다루기 때문에 클라이언트 코드가 특정 구현 클래스에 의존하지 않고도 동작할 수 있음
차이점



목적 객체에 새로운 기능을 동적으로 추가하는 것이 주 목적이며 기본 객체에 여러 데코레이터를 겹쳐 씌우면서 기능을 확장 객체를 트리 구조로 구성하여 부분-전체 계층 구조를 표현하는 것이 주 목적이며 이를 통해 개별 객체와 복합 객체를 동일하게 다룰 수 있음
구조 데코레이터는 기본 객체를 래핑(wrapping)하여 기능을 추가하며 데코레이터는 같은 인터페이스를 구현하며, 내부적으로 실제 객체를 참조 컴포짓은 단일 객체와 복합 객체를 구성 요소로 취급하기 때문에 복합 객체는 자신의 자식들을 포함하며, 자식들도 다시 복합 객체일 수 있음
use case 데코레이터 패턴은 객체에 여러 기능을 동적으로 추가하고 싶을 때 사용 컴포짓 패턴은 계층적 구조를 표현하고 클라이언트가 단일 객체와 복합 객체를 동일하게 처리해야할 때 사용

 

데코레이터 패턴 구현 예시

 

1. Shape 인터페이스 (Component)

  • 기본 도형을 나타내는 인터페이스로 draw 메서드를 정의

 

 

2. Circle, Rectangle 클래스 (CompositeComponent)

  • Shape 인터페이스를 구현하는 구체적인 클래스들

 

 

3. ShapeDecorator 클래스 (Decorator)

  • Shape 인터페이스를 구현하는 추상 클래스
  • Shape 타입의 객체를 포함하고 있으며, draw() 메서드를 구현하여 내부 Shape 객체의 draw() 메서드를 호출


 

4.  RedShapeDecorator 클래스 (ConcreteDecorator)

  • ShapeDecorator 클래스를 상속받아 구체적인 데코레이터 클래스를 구현
  • draw() 메서드를 재정의하여 기본 Shape의 draw() 메서드를 호출하고, 추가적으로 빨간 테두리를 그리는 기능을 추가


 

5. Client 코드

  • 데코레이터 패턴을 사용하여 도형(Shape) 객체를 생성하고, 필요에 따라 색상 데코레이터(RedShapeDecorator)를 적용하는 클라이언트 코드
  • circle과 isColorRed라는 두 개의 boolean 변수를 사용하여 어떤 도형을 생성할지와 해당 도형에 빨간색 테두리를 적용할지 여부를 결정


 

데코레이터 패턴 장단점

 

장점

  • 데코레이터 패턴은 각 클래스가 하나의 책임만 가지도록 설계 가능하도록 지원
    • 기본 클래스는 기본 기능만을 담당하고, 데코레이터 클래스는 추가 기능을 담당
    • 이를 통해 클래스의 책임이 명확하게 분리 (SOLID의 SPR 원칙)

 

  • 데코레이터 패턴을 사용하면 클래스의 기존 코드를 변경하지 않고도 새로운 기능 추가 가능 (SOLID의 OCP 원칙)
  • 데코레이터와 기본 객체는 동일한 인터페이스를 구현하므로, 데코레이터가 기본 객체로서 대체 가능 (SOLID의 LSP 원칙)

 

단점

  • 남용하거나 지나치게 복잡하게 사용할 경우, 코드의 복잡성을 증가시켜 유지보수와 관리가 어려워질 수 있음

 

실무에서 쓰이는 데코레이터 패턴

 

1. 자바 컬렉션

  • Collections.checkedList는 런타임에 제네릭 타입을 확인하는 기능을 추가하며 이를 통해 컬렉션에 잘못된 타입의 객체가 추가되는 것을 방지
    • 기본 컬렉션 객체를 감싸서 타입 검사를 추가하며 실제 작업은 내부의 기본 컬렉션 객체에 위임되며, 추가적으로 타입 검사가 수행

 

  • Collections.unmodifiableList는 컬렉션을 수정할 수 없도록 만드는 기능을 추가합니다. 이를 통해 컬렉션을 읽기 전용으로 사용 가능
    • 기본 컬렉션 객체를 감싸서 수정 작업을 방지
    • 모든 읽기 작업은 내부의 기본 컬렉션 객체에 위임되며, 쓰기 작업은 예외를 발생시킴

 

 

2. HttpServletRequestDecorator, HttpServletHttpResponseDecorator

  • Spring WebFlux의 ServletHttpRequestDecorator와 ServletHttpResponseDecorator는 데코레이터 패턴을 사용하여 HTTP 요청 및 응답 객체에 추가 기능 제공
  • 이 데코레이터들은 원래의 HTTP 요청 및 응답 객체를 래핑 하여 기능을 확장하거나 수정할 수 있도록 지원


 

부연 설명

  • HTTP 요청과 응답에 특정 로깅 기능을 추가하는 데코레이터를 사용하여 WebFilter를 구현

 

참고

코딩으로 학습하는 GoF의 디자인 패턴 - 백기선 강사님

반응형