데코레이터 패턴이란?
데코레이터 패턴 클래스 다이어그램
데코레이터 패턴은 객체에 추가요소를 동적으로 더할 수 있다. 데코레이터를 사용하면 서브클레스를 만들 때보다 훨씬 유연하게 기능을 확장할 수 있습니다.
•
데코레이터 패턴은 Component클래스를 상속받는다.
◦
데코레이터 형식이 그 데코레이터로 감싸는 객체의 형식과 같다.
◦
상속으로 행동을 물려받는게 아니기 때문에 상속을 받아도 문제가 되지 않는다.
•
한 객체를 여러 개의 데코레이터로 감쌀 수 있다.
•
데코레이터는 자신이 장식하고 있는 객체에게 어떤 행동을 위임하는 일 말고도 추가작업을 수행할 수 있습니다.
•
객체는 언제든지 감쌀 수 있으므로 실행중에 필요한 데코레이터를 마음대로 적용할 수 있습니다.
요구사항
스타버즈의 음료 주문 시스템을 구축한다.
•
커피를 기반으로한 여러가지 음료들을 판매한다.
•
커피에 우유를 추가하면 라떼, 초콜릿을 추가하면 카페모카 등 다양한 형태로 변형될 수 있다.
해결 방법 1 : 상속을 통한 구현 (1)
단점
•
너무 많은 클래스가 만들어졌음
•
행동을 상속 받았기 때문에 확장에 어려움이 있음
해결 방법 2 : 상속을 통한 구현 (2)
슈퍼클래스에서 첨가물을 추가해서 각 클래스가 관리하는 방법
단점
•
클래스의 수는 적어졌지만, 슈퍼클래스의 의존성이 더욱 높아졌음
•
첨가물의 가격이 바뀔때마다 코드를 수정해야 함
•
첨가물의 종류가 많아지면 슈퍼클래스에서 메소드를 추가해줘야 함
•
새로운 음료가 첨가물이 포함되면 안되는 음료일 수 있음
해결 방법 3 : 데코리이터 패턴 적용
데코레이터 패턴을 적용한 모습
// 음료객체
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());
}
}
Java
복사
데코레이터가 적용된 스타버즈 시스템의 코드
장점
•
OCP(Open-Closed Principle, 개방폐쇄 원칙)를 지키며 기능을 확장할 수 있다.
•
추후 음료의 첨가물이 추가되거나, 음료가 추가되더라도 추가적인 수정을 요하지 않는다.
단점
•
데코레이터 패턴을 사용하면 관리해야 할 객체가 늘어나니 코딩 실수가 발생할 가능성이 높아진다.
◦
실제로는 팩토리나 빌더를 통해서 극복할 수 있다.