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 ↓ ![wrapper](https://imgur.com/LznGyxF.jpg "wrapper") 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 ![](https://i.imgur.com/kI0C8c0.png) Coffee shop example ![](https://i.imgur.com/FJZCRds.png) 左邊繼承會有一些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` `教學`