이론/디자인패턴

데코레이터 패턴

모달조아 2022. 11. 26. 14:19

데코레이터 패턴이란?

객체에 책임을 동적으로 추가하는 패턴을 말합니다.

 

데코레이터 패턴을 주로 사용하는 상황

  1. 클래스의 요소들을 조금씩 수정해가면서 사용하는 경우
  2. 여러 요소들을 조합하여 구성하는 경우

 

예시

데코레이터 패턴을 설명하는 대표적인 예시로 커피가 있습니다.

아메리카노 = 에스프레소 + 물

카페라떼 = 에스프레소 + 우유 + 휘핑크림

이런식으로 다양한 재료들을 합쳐서 커피를 만들어야한다고 합시다.

만약, 재료들을 전부 다 클래스로 구현해준다면 굉장히 비효율적일 것입니다. 새롭게 커피를 개발하여 새로운 재료가 필요하다면, 그럴 때마다 새롭게 재료의 클래스를 만들어줘야하기 때문입니다. 이를 해결하기 위해 데코레이터 패턴을 적용해봅시다.

public interface Ingredient {
    String add(); //재료 추가
}

재료라는 인터페이스를 만들고, 재료를 추가하는 행위를 정의합니다.

public class Espresso implements Ingredient {

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

커피의 근간이 되는 에스프레소입니다.

public abstract class Decorator implements Ingredient {
    private Ingredient coffeeIngredient ;
    
    public Decorator(Ingredient coffeeIngredient) {
        this.coffeeIngredient = coffeeIngredient ;
    }
    
    public String add() {
        return coffeeIngredient.add();
    }
}

Decorator는 커피 재료들의 근간이 되는 추상클래스입니다. 추가되는 재료들은 클래스를 상속 받아 재료를 추가합니다.

public class WaterDecorator extends Decorator {
    public WaterDecorator(Ingredient coffeeIngredient) {
        super(coffeeIngredient);
    }
    
    @Override
    public String add() {
        return super.add() + " + 물";
    }
}
public class MilkDecorator extends Decorator {
    public MilkDecorator(Ingredient coffeeIngredient) {
        super(coffeeIngredient);
    }
    
    @Override
    public String add() {
        return super.add() + " + 우유";
    }
}
public class Main {

    public static void main(String[] args) {
        Ingredient espresso = new Espresso();
        System.out.println("에스프레소 : " + espresso.add());
        
        Ingredient americano = new WaterDecorator(new Espresso());
        System.out.println("아메리카노 : " + americano.add());
        
        Ingredient latte = new MilkDecorator(new WaterDecorator(new Espresso()));
        System.out.println("라떼 : " + latte.add());
    }
}

이처럼 동적으로 원하는 것을 추가해줄 수 있는 장점이 있습니다.