---
# System prepended metadata

title: Design Pattern --- (3) Decorator Pattern
tags: [Design Pattern, Java, 教學]

---

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` `教學`
