글 검색

공개된 글의 제목과 본문을 검색합니다.

    닫기 Esc

    데코레이터 패턴이란?#

    데코레이터 패턴 클래스 다이어그램
    데코레이터 패턴 클래스 다이어그램

    데코레이터 패턴은 객체에 추가요소를 동적으로 더할 수 있다. 데코레이터를 사용하면 서브클레스를 만들 때보다 훨씬 유연하게 기능을 확장할 수 있습니다.

    • 데코레이터 패턴은 Component클래스를 상속받는다.
      • 데코레이터 형식이 그 데코레이터로 감싸는 객체의 형식과 같다.
      • 상속으로 행동을 물려받는게 아니기 때문에 상속을 받아도 문제가 되지 않는다.
    • 한 객체를 여러 개의 데코레이터로 감쌀 수 있다.
    • 데코레이터는 자신이 장식하고 있는 객체에게 어떤 행동을 위임하는 일 말고도 추가작업을 수행할 수 있습니다.
    • 객체는 언제든지 감쌀 수 있으므로 실행중에 필요한 데코레이터를 마음대로 적용할 수 있습니다.

    요구사항#

    스타버즈의 음료 주문 시스템을 구축한다.

    • 커피를 기반으로한 여러가지 음료들을 판매한다.
    • 커피에 우유를 추가하면 라떼, 초콜릿을 추가하면 카페모카 등 다양한 형태로 변형될 수 있다.

    해결 방법 1 : 상속을 통한 구현 (1)#

    단점#

    • 너무 많은 클래스가 만들어졌음
    • 행동을 상속 받았기 때문에 확장에 어려움이 있음

    해결 방법 2 : 상속을 통한 구현 (2)#

    슈퍼클래스에서 첨가물을 추가해서 각 클래스가 관리하는 방법

    단점#

    • 클래스의 수는 적어졌지만, 슈퍼클래스의 의존성이 더욱 높아졌음
    • 첨가물의 가격이 바뀔때마다 코드를 수정해야 함
    • 첨가물의 종류가 많아지면 슈퍼클래스에서 메소드를 추가해줘야 함
    • 새로운 음료가 첨가물이 포함되면 안되는 음료일 수 있음

    해결 방법 3 : 데코리이터 패턴 적용#

    데코레이터 패턴을 적용한 모습
    데코레이터 패턴을 적용한 모습
    java
    // 음료객체
    public abstract class Beverage {
        String description = "제목없음";
        public String getDescription() {
            return description;
        }
        public abstract double cose();
    }
    
    // Beverage 데코레이터
    public abstract class CondimentDecorator extends Beverage {
        Beverage beverage;                          // 데코레이터가 감쌀 음료 객체
        public abstract String getDescription();    // 객체에 값을 더해 출력할 설명 추상 메소드
    }
    
    public class Espresso extends Beverage {
        public Espresso() {
            description = "에스프레소";
        }
    
        public double cost() {
            return 1.99;
        }
    }
    
    public class Mocha extends CondimentDecorator {
        public Mocha(Beverage beverage) {
            this.beverage = beverage;
        }
    
        public String getDescription() {
            return beverage.getDescription() + ", 모카";
        }
    
        public double cost() {
            return beverage.cost() + .20;
        }
    }
    
    public class StarbuzzCoffe {
        public static void main(String args[]) {
            // 베이스가 될 음료 객체 생성
            Beverage beverage = new Espresso();
            System.out.println(beverage.getDescription() + " $" + beverage.cost());
    
            // 모카 데코레이터로 객체를 장식!
            beverage = new Mocha(beverage);
            System.out.println(beverage.getDescription() + " $" + beverage.cost());
        }
    }
    데코레이터가 적용된 스타버즈 시스템의 코드

    장점#

    • OCP(Open-Closed Principle, 개방폐쇄 원칙)를 지키며 기능을 확장할 수 있다.
    • 추후 음료의 첨가물이 추가되거나, 음료가 추가되더라도 추가적인 수정을 요하지 않는다.

    단점#

    • 데코레이터 패턴을 사용하면 관리해야 할 객체가 늘어나니 코딩 실수가 발생할 가능성이 높아진다.
      • 실제로는 팩토리나 빌더를 통해서 극복할 수 있다.
    전체 글 둘러보기