Design Pattern --- (3) Decorator Pattern
===
## What problems can the decorator pattern solve?
* Responsibilities should be added to (and removed from) an object dynamically at run-time, in other words, ==the class explosion problem would be solved.== 對於新的功能有很多不同的組合方式就適合使用此pattern
* ==A flexible alternative to subclassing for extending functionality should be provided.== 擴充做在子類別,基底class可以不用被打開修改
For example:
This is a game,it has a profession of swordsman,and the promotion of swordsman is swordsman -> wild warrior -> knight -> hero,we can get a new skill while upgrading,and the old skills is still absoluetly usable.
So,a skill-set is based on the previous skills to grow gradually by promotion.here is a huge chance to complete the skill-set system through decorator pattern.
## When's a situation that intuitive consider decorator pattern to complete a system?
I want to **extend a new behavior** that is based on the old object,it's a good time to use **instead of inheritance.**
## How does decorator pattern work?
It actually has another name "**wrapper**",it means that I'll pack objects layer by layer,in other words,I can wrap a new object on outside of an old object.
like this ↓

So,when I creat a new object,I must let it be ==is a== and ==has a== interface,which **is a** is to have same method with interface,which **has a** is to invite the internally created objects through constructor,therefore,by this two things,I can complete a new external object.
* UML diagram for decorator pattern
General diagram

Coffee shop example

左邊繼承會有一些concrete class(e.g 咖啡豆),右邊則有decorator(abstract class)繼承基底後,再往下實作,這邊需注意,decorator class有一個變數是基底class,**用來表示上一層的物件**才能包裝(wrap)
## The example for real world
1. 咖啡店計價:
有不同咖啡豆不同價格,有不同東西可以加(奶泡,奶霜...)甚至可以加兩份以上且每個都東西都不同價格,這邊用decorator pattern的概念是說,我有一個基底叫做飲料,不斷裝飾不同東西進來(豆子, 奶霜, 等等),做成不同的組合
2. 點點卡設計:
點點卡有不同的形式,如條紋,點點,卡通圖案等等,
這邊用decorator pattern的概念是說,基點是空白卡片,不斷裝飾其他如條紋,點點近來,做成不同的組合
3. 騎士成長:
騎士成長可以分支: 聖騎士, 黑騎士, 英雄,每個都有不同的技能可以使用,這邊用decorator pattern的概念是說,基底是1轉騎士,不斷裝飾新的技能近來給不同轉職的分支,這邊或許直接使用繼承就可,因為大家技能都不一樣沒有所謂的**組合爆炸**的問題
## Implementation
==The first key is how to wrap an object on the main function,== new a concrete class and decorate it,
==Second key is how to design a decorator abstarct class==
Coffee shop example:
```java=
public class DecoratorPattern
{
public static void main(String[] args)
{
Beverage doubleMochaExpresso = new Expresso();
doubleMochaExpresso = new Mocha(doubleMochaExpresso);
doubleMochaExpresso = new Mocha(doubleMochaExpresso);
System.out.println("doubleMochaExpresso: " + doubleMochaExpresso.getDescirption());
System.out.println(doubleMochaExpresso.cost());
Beverage ExtraMilk_aMocha_DarkRoast = new DarkRoast();
ExtraMilk_aMocha_DarkRoast = new Milk(ExtraMilk_aMocha_DarkRoast);
ExtraMilk_aMocha_DarkRoast = new Milk(ExtraMilk_aMocha_DarkRoast);
ExtraMilk_aMocha_DarkRoast = new Milk(ExtraMilk_aMocha_DarkRoast);
ExtraMilk_aMocha_DarkRoast = new Mocha(ExtraMilk_aMocha_DarkRoast);
System.out.println("ExtraMilk_aMocha_DarkRoast: " + ExtraMilk_aMocha_DarkRoast.getDescirption());
System.out.println(ExtraMilk_aMocha_DarkRoast.cost());
}
}
abstract class Beverage
{
String descirption = "Beverage";
public String getDescirption()
{
return this.descirption;
}
abstract double cost();
}
class Expresso extends Beverage
{
public Expresso()
{
this.descirption = "Expresso";
}
public double cost()
{
return 10.0;
}
}
class DarkRoast extends Beverage
{
public DarkRoast()
{
this.descirption = "DarkRoast";
}
public double cost()
{
return 20.0;
}
}
abstract class Decorator extends Beverage
{
Beverage beverage ;
}
class Mocha extends Decorator
{
public Mocha(Beverage b)
{
this.descirption = "Mocha";
this.beverage = b;
}
public String getDescirption()
{
return this.beverage.getDescirption() + ", " + this.descirption;
}
public double cost()
{
return this.beverage.cost() + 1.0 ;
}
}
class Milk extends Decorator
{
public Milk(Beverage b)
{
this.descirption = "Milk";
this.beverage = b;
}
public String getDescirption()
{
return this.beverage.getDescirption() + ", " + this.descirption;
}
public double cost()
{
return this.beverage.cost() + 2.0 ;
}
}
/* outputs :
*
* doubleMochaExpresso: Expresso, Mocha, Mocha
* 12.0
* ExtraMilk_aMocha_DarkRoast: DarkRoast, Milk, Milk, Milk, Mocha
* 27.0
*
* */
```
## Reference
https://www.youtube.com/watch?v=GCraGHx6gso&t=1s
https://medium.com/bucketing/structural-patterns-decorator-design-pattern-94f17c6b5002
###### tags: `Design Pattern` `Java` `教學`