개발/DesignPatterns

3. Decorate Pattern(데코레이트 패턴)

huiyu 2014. 7. 6. 22:12

Decorator Design Pattern(데코레이터 패턴)


Define

 객체에 추가적인 요건을 동적으로 첨가한다. 데코레이터는 서브클래스를 만드는 것을 통해서 기능을 유연하게 확장할 수 있는 방법을 제공한다.


Structure

Decorator scheme

- 데코레이터(OptionalWrapper)의 슈퍼클래스(Interface)는 자신이 장식하고 있는 객체(CoreFunctionality)의 슈퍼클래스와 같다.


 Example)
Decorator example


Advantage

- 클래스의 기능들이 동적으로 변경될 소지가 있을 때 사용

- 클래스에 동적으로 추가하는 기능들이 앞으로도 더 추가될 수 있을 때 사용
- 클래스에 기능들을 여러개로 조합 될 때 미리 정의해두기 너무 많은 클래스가 생성되므로, 즉시 생성이 가능하게 할 때 사용
- 한 객체를 여러개의 데코레이터로 감쌀 수 있다.
- 실행 중 필요한 테코레이터를 마음대로 적용할 수 있다.


Code-Java

- HeadFirst example) Coffee

1. Component - Beverage/ ConcreteComponent - Espresso, HouseBlend, DarkRoast, Decaf

  - 최상단 Beverage클래스와 이를 상속하는 구체적인 커피종류들, 추상메소드 cost()를 상속받아 각각의 가격을 구현한다.

//Component public abstract class Beverage { String description = "제목없음"; public String getDescription(){ return description; } public abstract double cost(); } //ConcreteComponent class Espresso extends Beverage{ public Espresso(){ description = "에스프레소"; } public double cost(){ return 1.99; } } class HouseBlend extends Beverage{ public HouseBlend(){ description = "하우스 블렌드 커피"; } public double cost(){ return .89; } } class DarkRoast extends Beverage{ public DarkRoast(){ description = "다크로스트 커피"; } public double cost(){ return .99; } } class Decaf extends Beverage{ public Decaf(){ description = "디카프"; } public double cost(){ return 1.05; } }

2. Decorate - CondimentDecorator // ConcreteDecorate - Soy,Whip, SteamMilk

- 마찬가지로 Beverage 클래스를 상속받고 Decorate를 상속받은 Soy,Whip,SteamMilk 객체가 음료를 꾸며준다.

각 객체는 Beverage클래스를 가지고 있다.

//Decorate
public abstract class CondimentDecorator extends Beverage{
	public abstract String getDescription();
}

//ConcreteDecorate
class Mocha extends CondimentDecorator{
	Beverage beverage;

	public Mocha(Beverage beverage) {
		this.beverage = beverage;
	}
	
	@Override
	public String getDescription() {
		// TODO Auto-generated method stub
		return beverage.getDescription() + ", 모카";
	}

	@Override
	public double cost() {
		// TODO Auto-generated method stub
		return .20 + beverage.cost();
	}
	
}

class Soy extends CondimentDecorator{
	Beverage beverage;

	public Soy(Beverage beverage) {
		this.beverage = beverage;
	}
	
	@Override
	public String getDescription() {
		// TODO Auto-generated method stub
		return beverage.getDescription() + ", 두유";
	}

	@Override
	public double cost() {
		// TODO Auto-generated method stub
		return .15 + beverage.cost();
	}
	
}

class Whip extends CondimentDecorator{
	Beverage beverage;

	public Whip(Beverage beverage) {
		this.beverage = beverage;
	}
	
	@Override
	public String getDescription() {
		// TODO Auto-generated method stub
		return beverage.getDescription() + ", ��핑";
	}

	@Override
	public double cost() {
		// TODO Auto-generated method stub
		return .10 + beverage.cost();
	}
	
}


class SteamMilk extends CondimentDecorator{
	Beverage beverage;

	public SteamMilk(Beverage beverage) {
		this.beverage = beverage;
	}
	
	@Override
	public String getDescription() {
		// TODO Auto-generated method stub
		return beverage.getDescription() + ", 스팀 밀크";
	}

	@Override
	public double cost() {
		// TODO Auto-generated method stub
		return .10 + beverage.cost();
	}
	
}


3. Main

public class Main {
	public static void main(String[] args) {
		Beverage beverage = new Espresso();
		System.out.println(beverage.getDescription() + " $"+beverage.cost());
		
		Beverage beverage2 = new DarkRoast();
		beverage2 = new Mocha(beverage2);
		beverage2 = new Mocha(beverage2);
		beverage2 = new Whip(beverage2);
		System.out.println(beverage2.getDescription() + " $"+beverage2.cost());
		
		Beverage beverage3 = new HouseBlend();
		beverage3 = new Soy(beverage3);
		beverage3 = new Mocha(beverage3);
		beverage3 = new Whip(beverage3);
		System.out.println(beverage3.getDescription() + " $"+beverage3.cost());
		
	}
}

---실행결과---

에스프레소 $1.99

다크로스트 커피, 모카, 모카, 휘핑 $1.49

하우스 블렌드 커피, 두유, 모카, 휘핑 $1.34


-> 동적으로 커피를 감싸는 토핑을 추가할 수 있고, 이를 포함한 가격을 구해낼 수 있다.

다음과 같은 이미지.




728x90
반응형