본문 바로가기

디자인 패턴

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

1. 정의

  • 객체에 추가 요소를 동적으로 추가한다. 서브 클래스를 만들 때 보다 훨씬 유연하게 기능을 확장할 수 있다.

2. 예시

  • 커피에 2샷과 모카를 추가한다.

3. 그림

4. 클래스 다이어그램

5. 코드

public class Clinet {
    public static void main(String[] args){
        
        Beverage coffee = new Coffee();
        coffee = new MochaAdditive(new ShotAdditive(new ShotAdditive(coffee)));

        System.out.println("[주문]");
        System.out.println(coffee.getDescription());
        System.out.println("-------");
        System.out.println("[가격]\\n" + coffee.cost());
    }
}
/* 출력
[주문]
커피
샷추가
샷추가
모카 추가
-------
[가격]
2800.0
*/
public abstract class Beverage {
    String description = "";

    public String getDescription(){
        return this.description;
    }

    public abstract double cost();
}
public class Coffee extends Beverage{

   Coffee(){
       this.description = "커피";
   }

    @Override
    public double cost() {
        return 2_000;
    }
}
public abstract class Additive extends Beverage{
    Beverage beverage;
    public abstract String getDescription();
}
public class ShotAdditive extends Additive{

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

    @Override
    public String getDescription() {
        return this.beverage.getDescription() + "\\n샷추가";
    }

    @Override
    public double cost() {
        return beverage.cost() + 300;
    }
}
public class MochaAdditive extends Additive{

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

    @Override
    public String getDescription() {
        return beverage.getDescription() + "\\n모카 추가";
    }

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

https://github.com/kang-seongbeom/design_pattern

💡 Github에서 디자인 패턴 코드를 볼 수 있습니다.

6. 설명

  • Coffee와 Additive는 Beverage를 상속한다.
  • Coffee에 샷을 두 번 추가한다. (데코레이팅)
  • Coffee에 모카를 한 번 추가한다. (데코레이팅)
  • 데코레이터(샷, 모카)의 생성자를 통해 피데코레이터(커피)를 전달한다.
  • 생성자를 통해 전달되는 참조변수는 Beverage다.
  • 즉, Beverage를 상속하는 어떤것이든 전달할 수 있다.

💡 데코레이터와 피데코레이터는 같은 것을 상속(extends) 또는 구현(implements)해야 한다.

7. 참고

// 데코레이터 패턴
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));