概述
上一篇我們學習了擴充卡模式,今天我們接着學習裝飾模式。
定義和結構
裝飾者模式:動态地将責任附加到對象上,若要擴充功能,裝飾者提供比繼承更有彈性的替代方案

裝飾模式的角色有:
1. 抽象元件(Component)角色:給出一個抽象接口,以規範準備接收附加責任的對象。
2. 具體元件(ConcreteComponent)角色:定義一個将要接收附加責任的類
3. 裝飾者(Decorator)角色: 持有一個構件對象的執行個體。并實作一緻的接口。
4. 具體裝飾(Concrete Decorator)角色:負責給構件對象添加上附加的責任。
以咖啡調料品為例
假設有這樣一個場景:張三買了一杯25元的美式咖啡,喝了幾口,太苦了。然後加了2元一份的糖包(sugar),李四買了一杯30元的拿鐵,然後在裡面加了一份5元的牛奶(milk)。這樣一種情況,就屬于裝飾器模式,咖啡作為元件,調料包作為裝飾器。
類圖
抽象咖啡類(Coffee)
package com.decorate;
/**
* 抽象咖啡類
*
* @author xiang.wei
* @create 2018/4/10 19:44
*/
public abstract class Coffee {
//咖啡資訊
private String coffeeInfo = "普通咖啡";
public String getCoffeeInfo() {
return coffeeInfo;
}
public abstract int cost();
}
具體咖啡類
package com.decorate;
/**
* 美式咖啡類
* @author xiang.wei
* @create 2018/4/11 13:50
*/
public class Americano extends Coffee {
@Override
public String getCoffeeInfo() {
return "美式咖啡";
}
@Override
public int cost() {
return 25;
}
}
package com.decorate;
/**
* 拿鐵類
*
* @author xiang.wei
* @create 2018/4/11 13:49
*/
public class Latte extends Coffee {
@Override
public String getCoffeeInfo() {
return "拿鐵";
}
@Override
public int cost() {
return 30;
}
}
調料類(Flavour):
package com.decorate;
/**
* 配料抽象類
* @author xiang.wei
* @create 2018/4/11 13:54
*/
public abstract class Flavour extends Coffee {
@Override
public abstract String getCoffeeInfo();
}
調料類(Flavour)繼承了咖啡類(Coffee),并重寫了
getCoffeeInfo()
方法。
具體調料類
package com.decorate;
/**
* 配料牛奶類
*
* @author xiang.wei
* @create 2018/4/11 13:54
*/
public class Milk extends Flavour {
private Coffee coffee;
public Milk(Coffee coffee) {
this.coffee = coffee;
}
@Override
public String getCoffeeInfo() {
return coffee.getCoffeeInfo()+"加了牛奶";
}
@Override
public int cost() {
return coffee.cost()+5;
}
}
package com.decorate;
/**
* 配料糖類
*
* @author xiang.wei
* @create 2018/4/11 13:54
*/
public class Sugar extends Flavour {
private Coffee coffee;
public Sugar(Coffee coffee) {
this.coffee = coffee;
}
@Override
public String getCoffeeInfo() {
return coffee.getCoffeeInfo()+"加了糖";
}
@Override
public int cost() {
return coffee.cost()+3;
}
}
用戶端類:
package com.decorate;
/**
* @author xiang.wei
* @create 2018/4/11 14:18
*/
public class Client {
public static void main(String[] args) {
Coffee coffee1 = new Americano();
Coffee coffee2 = new Latte();
Flavour flavour = new Sugar(coffee1);
System.out.println(flavour.getCoffeeInfo()+"現在的價格是:"+flavour.cost());
Flavour flavour1 = new Milk(coffee2);
System.out.println(flavour1.getCoffeeInfo()+"現在的價格是:"+flavour1.cost());
}
}
運作結果是:
美式咖啡加了糖現在的價格是:28
拿鐵加了牛奶現在的價格是:35
優缺點
- 這種比繼承更加靈活機動的特性,也同時意味着更加多的複雜性。
- 裝飾模式會導緻設計中出現許多小類,如果過度使用,會使程式變得很複雜。
- 裝飾模式是針對抽象元件(Component)類型程式設計。但是,如果你要針對具體元件程式設計時,就應該重新思考你的應用架構,以及裝飾者是否合适。當然也可以改變Component接口,增加新的公開的行為,實作“半透明”的裝飾者模式。在實際項目中要做出最佳選擇。