디자인 패턴

Decorator Pattern

kyoulho 2024. 5. 5. 15:36

데코레이터 패턴은 객체의 구조를 변경하지 않고 기능을 동적으로 확장할 수 있는 디자인 패턴 중 하나이다.

이 패턴은 객체에 새로운 기능을 추가하거나 변경할 때, 서브 클래스를 생성하지 않고도 구현할 수 있도록 한다.

 

데코레이터 패턴의 주요 구성 요소

  1. Component(구성 요소):
    • 기본 기능을 정의하는 인터페이스 또는 추상 클래스이다.
  2. ConcreteComponent(구체적인 구성 요소):
    • Component의 구현 클래스로, 실제로 기본 기능을 구현한다.
  3. Decorator(데코레이터):
    • Component를 상속하며, Component의 하위 클래스들을 데코레이팅하는 역할을 한다. 데코레이터는 동일한 인터페이스를 갖고 있어야 한다.
  4. ConcreteDecorator(구체적인 데코레이터):
    • Decorator의 구현 클래스로, 실제로 기능을 추가하거나 변경하는 역할을 한다.

 

주의 사항

데코레이터 패턴을 쓰면 관리해야 할 객체가 늘어난다. 때문에 실제로는 팩토리나 빌더 같은 다른 패턴으로 데코레이터를 만들어 사용한다.

데코레이터 내부의 요소(구체적인 구성 요소)로 돌아가는 코드를 만들어야 한다면 데코레이터 패턴 사용을 다시 한번 생각해 봐야 한다.

 

예제

// 컴포넌트 인터페이스
interface Beverage {
    double cost(); // 가격을 반환하는 메서드
    String getDescription(); // 설명을 반환하는 메서드
}

// 구체적인 컴포넌트
class Espresso implements Beverage {
    @Override
    public double cost() {
        return 1.99;
    }

    @Override
    public String getDescription() {
        return "에스프레소";
    }
}

// 데코레이터 팩토리 인터페이스
interface CondimentFactory {
    Beverage addCondiment(Beverage beverage);
}

// 구체적인 데코레이터 팩토리
class MilkFactory implements CondimentFactory {
    @Override
    public Beverage addCondiment(Beverage beverage) {
        return new Milk(beverage);
    }
}

class MochaFactory implements CondimentFactory {
    @Override
    public Beverage addCondiment(Beverage beverage) {
        return new Mocha(beverage);
    }
}

// 데코레이터
abstract class CondimentDecorator implements Beverage {
    protected Beverage beverage;

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

// 구체적인 데코레이터
class Milk extends CondimentDecorator {
    public Milk(Beverage beverage) {
        super(beverage);
    }

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

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

class Mocha extends CondimentDecorator {
    public Mocha(Beverage beverage) {
        super(beverage);
    }

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

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

public class Main {
    public static void main(String[] args) {
        // 팩토리를 이용하여 데코레이터 생성
        CondimentFactory milkFactory = new MilkFactory();
        CondimentFactory mochaFactory = new MochaFactory();

        // 주문: 에스프레소에 우유와 모카 추가
        Beverage beverage = new Espresso();
        beverage = milkFactory.addCondiment(beverage);
        beverage = mochaFactory.addCondiment(beverage);

        System.out.println("주문: " + beverage.getDescription());
        System.out.println("가격: $" + beverage.cost());
    }
}

'디자인 패턴' 카테고리의 다른 글

Factory Pattern  (0) 2024.05.18
Facade Pattern  (0) 2024.05.12
Composite Pattern  (1) 2024.05.01
Command Pattern  (0) 2024.04.28
Chain Of Responsibility Pattern  (0) 2024.04.27