今天給大家說一下23種設計模式中的第九種——裝飾者模式。一般的,我們爲了擴展一個類經常使用繼承方式實現,由於繼承爲類引入靜態特徵,並且隨着擴展功能的增多,子類會很膨脹。這個時候,我們就需要用到裝飾者模式了,它可以實現在不增加很多子類的情況下擴展類的功能。
概念:
裝飾者模式(Decorator Pattern)允許向一個現有的對象添加新的功能,同時又不改變其結構。這種類型的設計模式屬於結構型模式,它是作爲現有的類的一個包裝。這種模式創建了一個裝飾類,用來包裝原有的類,並在保持類方法簽名完整性的前提下,提供了額外的功能。
特點:
優點:
- 採用裝飾者模式擴展對象的功能比採用繼承方式更加靈活。
- 裝飾者模式可以設計出多個不同的具體裝飾類,創造出多個不同行爲的組合。
缺點:
- 雖然裝飾者模式能夠動態地將責任附加到對象上,但是他會產生許多的細小對象,增加了系統的複雜度。
類圖分析:
代碼:
Drink 飲品抽象類
package cn.ppdxzz.decorator;
/**
* Description:Drink飲品抽象類
*
* @Date: 2020/4/8
* @Author: PeiChen JavaAnything
*/
public abstract class Drink {
private String description;//描述
private float price = 0.0f;//價格
//計算總價格的抽象方法
public abstract float cost();
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
}
咖啡緩衝類
package cn.ppdxzz.decorator;
/**
* Description:咖啡類
*
* @Date: 2020/4/8
* @Author: PeiChen JavaAnything
*/
public class Coffee extends Drink {
@Override
public float cost() {
return super.getPrice();
}
}
無因咖啡
package cn.ppdxzz.decorator;
/**
* Description:無因咖啡
*
* @Date: 2020/4/8
* @Author: PeiChen JavaAnything
*/
public class Decaf extends Coffee {
public Decaf() {
setDescription("無因咖啡");
setPrice(2.0f);
}
}
美式咖啡
package cn.ppdxzz.decorator;
/**
* Description:美式咖啡
*
* @Date: 2020/4/8
* @Author: PeiChen JavaAnything
*/
public class LongBlack extends Coffee {
public LongBlack() {
setDescription("美式咖啡");
setPrice(3.0f);
}
}
裝飾者類
package cn.ppdxzz.decorator;
/**
* Description:裝飾者類
*
* @Date: 2020/4/8
* @Author: PeiChen JavaAnything
*/
public class Decorator extends Drink {
private Drink drink;
public Decorator(Drink drink) {
this.drink = drink;
}
@Override
public float cost() {
return super.getPrice() + drink.cost();
}
@Override
public String getDescription() {
//drink.getDescription() 輸出被裝飾者的描述
return super.getDescription() + ":" + super.getPrice() +"" + " + " + drink.getDescription();
}
}
牛奶
package cn.ppdxzz.decorator;
/**
* Description:牛奶
*
* @Date: 2020/4/8
* @Author: PeiChen JavaAnything
*/
public class Milk extends Decorator {
public Milk(Drink drink) {
super(drink);
setDescription("牛奶");
setPrice(2.0f);
}
}
巧克力
package cn.ppdxzz.decorator;
/**
* Description:巧克力
*
* @Date: 2020/4/8
* @Author: PeiChen JavaAnything
*/
public class Chocolate extends Decorator{
public Chocolate(Drink drink) {
super(drink);
setDescription("巧克力");
setPrice(2.0f);
}
}
咖啡訂單
package cn.ppdxzz.decorator;
/**
* Description:裝飾者模式咖啡訂單,無因咖啡+兩份牛奶+一份巧克力
*
* @Date: 2020/4/8
* @Author: PeiChen JavaAnything
*/
public class CoffeeOrder {
public static void main(String[] args) {
//1.點一份無因咖啡
Drink order = new Decaf();
System.out.println("無因咖啡的費用:" + order.getPrice());
System.out.println("無因咖啡的描述:" + order.getDescription());
//2.加一份牛奶
order = new Milk(order);
System.out.println("訂單加入一份牛奶的費用:" + order.cost());
System.out.println("訂單加入一份牛奶的描述:" + order.getDescription());
order = new Milk(order);
System.out.println("訂單加入兩份牛奶的費用:" + order.cost());
System.out.println("訂單加入兩份牛奶的描述:" + order.getDescription());
order = new Chocolate(order);
System.out.println("訂單加入兩份牛奶和一份巧克力的費用:" + order.cost());
System.out.println("訂單加入兩份牛奶和一份巧克力的描述:" + order.getDescription());
}
}
運行結果:
總結:
- Java 的 IO 結構,
FilterInputStream
就是一個裝飾者。 - 裝飾類和被裝飾類可以獨立發展,不會相互耦合,裝飾模式是繼承的一個替代模式,裝飾模式可以動態擴展一個實現類的功能。
- 裝飾模式增加了許多子類,如果過度使用會使程序變得很複雜。
微信公衆號,JavaAnything,期待你的關注!