데코레이터 패턴

Bo Ram·2025년 3월 6일

핵심 개념

데코레이터 패턴은 객체에 동적으로 새로운 기능을 추가할 수 있도록 하는 패턴이다.
이 패턴은 상속을 사용하지 않고, 기존 코드 변경 없이 기능을 확장할 수 있도록 해준다.

구성 요소

  1. Component(컴포넌트, 기본 인터페이스)

    • 기본 기능을 정의하는 인터페이스.
  2. ConcreteComponent(구체적인 컴포넌트)

    • 실제 동작을 구현한 기본 클래스.
  3. Decorator(데코레이터, 기본 컴포넌트를 감싸는 역할)

    • Component를 상속받아 추가 기능을 더하는 역할.
  4. ConcreteDecorator(구체적인 데코레이터)

    • 추가적인 기능을 구현하는 클래스.

적용 예시 (커피 주문 시스템)

// 컴포넌트 (커피 인터페이스)
public abstract class Beverage {
    String description = "알 수 없는 음료";

    public String getDescription() {
        return description;
    }

    public abstract double cost();
}

// 구체적인 컴포넌트 (에스프레소)
public class Espresso extends Beverage {
    public Espresso() {
        description = "에스프레소";
    }

    @Override
    public double cost() {
        return 1.99;
    }
}

// 데코레이터 (추상 클래스)
public abstract class CondimentDecorator extends Beverage {
    public abstract String getDescription();
}

// 구체적인 데코레이터 (우유 추가)
public class Milk extends CondimentDecorator {
    Beverage beverage;

    public Milk(Beverage beverage) {
        this.beverage = beverage;
    }

    @Override
    public String getDescription() {
        return beverage.getDescription() + ", 우유";
    }

    @Override
    public double cost() {
        return beverage.cost() + 0.30;
    }
}

// 실행 코드
public class CoffeeShop {
    public static void main(String[] args) {
        Beverage espresso = new Espresso();
        System.out.println(espresso.getDescription() + " $" + espresso.cost());

        Beverage espressoWithMilk = new Milk(new Espresso());
        System.out.println(espressoWithMilk.getDescription() + " $" + espressoWithMilk.cost());
    }
}

실행 결과

에스프레소 $1.99
에스프레소, 우유 $2.29

알아야 할 점

  • 상속보다 조합(Composition)이 강력한 이유

    • 상속을 사용하면 하위 클래스를 계속 추가해야 하지만, 데코레이터 패턴은 조합을 통해 새로운 기능을 쉽게 확장할 수 있다.
  • 데코레이터 중첩 가능

    • 여러 개의 데코레이터를 감싸면서 기능을 확장할 수 있다.
      (예: new Milk(new Mocha(new Espresso())))
  • 스트림 API와 유사

    • Java의 BufferedInputStream, DataInputStream 등이 데코레이터 패턴을 활용한 대표적인 예시.
    • InputStream을 감싸면서 추가 기능을 더하는 방식.

옵저버 패턴 vs 데코레이터 패턴 차이점

구분옵저버 패턴 (Observer Pattern)데코레이터 패턴 (Decorator Pattern)
목적객체 간 일대다 관계에서 상태 변경을 알림객체에 새로운 기능을 동적으로 추가
구조Subject(발행자)와 Observer(구독자) 간의 관계기존 객체를 감싸는(Wrapper) 방식
관계느슨한 결합 (Subject는 Observer를 모름)원본 객체를 감싸면서 기능을 확장
사용 예시GUI 이벤트 리스너, 뉴스 구독 시스템Java I/O 스트림 (BufferedInputStream)
단점옵저버가 많아지면 업데이트 비용 증가중첩이 많아지면 객체가 복잡해질 수 있음
profile
사부작ㅤ사부작

0개의 댓글