커피 전문점을 생각해보자.
객체 마을에 스타버즈라는 커피숍이 있다.
커피의 종류는 여러가지에 추가할수 있는 메뉴가 수십가지가 될수도 있다.
다음 그림을 보자.

이렇게 클래스 개수가 엄청나게 늘어난다. 커피 메뉴가 더 늘어나면 훨씬 더 늘어날 것이다.
상속이 강력하긴 하지만, 모든 서브 클래스에서는 똑같은 행동을 상속받게 된다.
이럴때, 구성을 통해서 행동을 확장하게 되면 실행중에 동적으로 행동을 설정할 수있다. (스트레티지 패턴)
디자인 원칙 ) 클래스는 확장에 대해서는 열려있어야 하지만,
코드 변경에 대해서는 닫혀 있어야 한다.
O.C.P ( Open-Closed Principle)
*무조건 OCP를 적용하는 것은 시간 낭비가 될수도 있다. 코드를 확장해야 할 부분을 선택할때는 세심한 주의를 기울여야 한다.
커피 메뉴 중 DarkRoast 메뉴를 한번 살펴 보자.
DarkRoast 커피에 Whip, Mocha를 추가 한다고 해보자.

cost() 메소드로 이 음료를 계산을 해보자.

어떻게 이게 가능한것인지, 이따가 코드로 살펴보자.
데코레이터 패턴 ) 객체의 추가적인 요건을 동적으로 첨가한다. 데코레이터는 서브클래스를
만드는 것을 통해 기능을 유연하게 확장할 수 있는 방법을 제공한다.
*데코레이터 패턴 : 클래스 다이어그램

StarBuzz 커피 : 클래스 다이어 그램

#코드
public class HouseBlend extends Beverage {
public HouseBlend() {
description = "House Blend Coffee";
}
public double cost() {
return .89;
}
}
public class Mocha extends CondimentDecorator {
public Mocha(Beverage beverage) { //beverage 객체는 슈퍼클래스에서 상속받았다.
this.beverage = beverage;
}
public String getDescription() {
return beverage.getDescription() + ", Mocha";
}
public double cost() {
return .20 + beverage.cost();
}
}
public class Soy extends CondimentDecorator {
public Soy(Beverage beverage) {
this.beverage = beverage;
}
public String getDescription() {
return beverage.getDescription() + ", Soy";
}
public double cost() {
return .15 + beverage.cost();
}
}
// main 코드
Beverage beverage = new HouseBlend();
beverage = new Mocha(beverage);
beverage = new Soy(beverage);
// 음료 이름과 가격 출력.
System.out.println( beverage.getDescription() + "$" + beverage.cost() );
Beverage beverage = new HouseBlend();
//여기서 HouseBlend의 생성자가 호출이 된다. description에 Houseblend가 저장되고,
//인스턴스 변수가 메모리에 올라가게 된다.
berverge = new Mocha(beverage);
//Mocha 생성자에 매개변수로 HouseBlend객체를 넘겨준다. 그럼 beverage에 HouseBlend객체가 저장된다.
beverage = new Soy(beverage);
//Soy 생성자에 매개변수로 Mocha객체를 넘겨준다. 그럼 beverage에 Mocha객체가 저장된다.
//이제 beverage.cost() 를 호출하게 되면-
//마지막에 저장된 객체가 Soy 이므로 Soy.cost()가 호출이 된다.
/*
(실행되는 순서) 1. Soy.cost() -> 2. Mocha.cost() -> 3. HouseBlend.cost()
------------------------------------------------------------------------------
1. 0.15 + (Mocha)beverage.cost()
2. 0.20 + 0.15 + (HouseBlend)beverage.cost()
3. 0.99 + 0.22 + 0.15
*/
커피 전문점을 생각해보자.
객체 마을에 스타버즈라는 커피숍이 있다.
커피의 종류는 여러가지에 추가할수 있는 메뉴가 수십가지가 될수도 있다.
다음 그림을 보자.

이렇게 클래스 개수가 엄청나게 늘어난다. 커피 메뉴가 더 늘어나면 훨씬 더 늘어날 것이다.
상속이 강력하긴 하지만, 모든 서브 클래스에서는 똑같은 행동을 상속받게 된다.
이럴때, 구성을 통해서 행동을 확장하게 되면 실행중에 동적으로 행동을 설정할 수있다. (스트레티지 패턴)
디자인 원칙 ) 클래스는 확장에 대해서는 열려있어야 하지만,
코드 변경에 대해서는 닫혀 있어야 한다.
O.C.P ( Open-Closed Principle)
*무조건 OCP를 적용하는 것은 시간 낭비가 될수도 있다. 코드를 확장해야 할 부분을 선택할때는 세심한 주의를 기울여야 한다.
커피 메뉴 중 DarkRoast 메뉴를 한번 살펴 보자.
DarkRoast 커피에 Whip, Mocha를 추가 한다고 해보자.

cost() 메소드로 이 음료를 계산을 해보자.

어떻게 이게 가능한것인지, 이따가 코드로 살펴보자.
데코레이터 패턴 ) 객체의 추가적인 요건을 동적으로 첨가한다. 데코레이터는 서브클래스를
만드는 것을 통해 기능을 유연하게 확장할 수 있는 방법을 제공한다.
*데코레이터 패턴 : 클래스 다이어그램

StarBuzz 커피 : 클래스 다이어 그램

#코드
public class HouseBlend extends Beverage {
public HouseBlend() {
description = "House Blend Coffee";
}
public double cost() {
return .89;
}
}
public class Mocha extends CondimentDecorator {
public Mocha(Beverage beverage) { //beverage 객체는 슈퍼클래스에서 상속받았다.
this.beverage = beverage;
}
public String getDescription() {
return beverage.getDescription() + ", Mocha";
}
public double cost() {
return .20 + beverage.cost();
}
}
public class Soy extends CondimentDecorator {
public Soy(Beverage beverage) {
this.beverage = beverage;
}
public String getDescription() {
return beverage.getDescription() + ", Soy";
}
public double cost() {
return .15 + beverage.cost();
}
}
// main 코드
Beverage beverage = new HouseBlend();
beverage = new Mocha(beverage);
beverage = new Soy(beverage);
// 음료 이름과 가격 출력.
System.out.println( beverage.getDescription() + "$" + beverage.cost() );
Beverage beverage = new HouseBlend();
//여기서 HouseBlend의 생성자가 호출이 된다. description에 Houseblend가 저장되고,
//인스턴스 변수가 메모리에 올라가게 된다.
berverge = new Mocha(beverage);
//Mocha 생성자에 매개변수로 HouseBlend객체를 넘겨준다. 그럼 beverage에 HouseBlend객체가 저장된다.
beverage = new Soy(beverage);
//Soy 생성자에 매개변수로 Mocha객체를 넘겨준다. 그럼 beverage에 Mocha객체가 저장된다.
//이제 beverage.cost() 를 호출하게 되면-
//마지막에 저장된 객체가 Soy 이므로 Soy.cost()가 호출이 된다.
/*
(실행되는 순서) 1. Soy.cost() -> 2. Mocha.cost() -> 3. HouseBlend.cost()
------------------------------------------------------------------------------
1. 0.15 + (Mocha)beverage.cost()
2. 0.20 + 0.15 + (HouseBlend)beverage.cost()
3. 0.99 + 0.22 + 0.15
*/