定義
動(dòng)態(tài)的將責(zé)任附加到對(duì)象上,若要擴(kuò)展功能,裝飾者模式提供了比繼承更具有彈性的方案脂矫。
為什么會(huì)出現(xiàn)這個(gè)設(shè)計(jì)模式
給對(duì)象擴(kuò)展行為的方法有兩種,一種是通過繼承霉晕,繼承是給類添加擴(kuò)展行為比較有效的辦法庭再,通過使用繼承,可以使得子類有自己的行為娄昆,還可以獲得父類的行為方法佩微,但是使用繼承是靜態(tài)的,在編譯的時(shí)候就已經(jīng)決定了子類有哪些行為萌焰。
當(dāng)然還可以使用關(guān)聯(lián)哺眯,將一個(gè)對(duì)象嵌入到另一個(gè)對(duì)象中,有一個(gè)對(duì)象來決定是否引用該對(duì)象來擴(kuò)展自己的行為扒俯,這是一種動(dòng)態(tài)的方式奶卓,我們可以在程序中動(dòng)態(tài)的決定和控制。
前面所說的兩種都會(huì)導(dǎo)致一種‘類爆炸’的情況出現(xiàn)撼玄,所以就出現(xiàn)了裝飾者模式夺姑。
認(rèn)識(shí)裝飾者模式
例如為咖啡店設(shè)計(jì)一個(gè)點(diǎn)咖啡的程序,采用飲料為主體掌猛,在運(yùn)行時(shí)以調(diào)料來‘裝飾’飲料盏浙,如果顧客要摩卡和奶泡深焙咖啡,那么,
- 拿一個(gè)深焙咖啡(DarkRoast)對(duì)象
- 以摩卡(Mocha)對(duì)象裝飾它
- 一奶泡(Whip)對(duì)象裝飾它
- 調(diào)用cost方法废膘,并依賴委托(delegate)將調(diào)料的錢加上去竹海。
裝飾者類圖結(jié)構(gòu)
image
實(shí)現(xiàn)裝飾者模式
情景:購(gòu)買咖啡時(shí)丐黄,會(huì)加入不同的調(diào)料斋配,根據(jù)不同的調(diào)料來收費(fèi)灌闺,也就是說不同的咖啡與不同的調(diào)料有N中不同的組合方式,也就是出現(xiàn)了不同組合就應(yīng)該有不同的價(jià)格桂对。結(jié)構(gòu)圖如下:
image
代碼實(shí)現(xiàn)
Beverage組件基類
public abstract class Beverage {
protected String description = "";
public String getDescription() {
return description;
}
public abstract double cost();
}
HouseBlend組件
public class HouseBlend extends Beverage {
public HouseBlend() {
description = "這是一杯綜合咖啡";
}
@Override
public double cost() {
return 0.89;
}
}
Espresso組件
public class Espresso extends Beverage{
public Espresso() {
description = "這是一杯濃縮咖啡";
}
@Override
public double cost() {
return 1.99;
}
}
Decat組件
public class Decat extends Beverage {
public Decat() {
description = "這是一杯深焙咖啡";
}
@Override
public double cost() {
return 0.99;
}
}
DarkRoast
public class DarkRoast extends Beverage{
public DarkRoast() {
description = "這是一杯低咖啡因咖啡";
}
@Override
public double cost() {
return 1.05;
}
}
配料基本類
public abstract class CondimentDecorator extends Beverage{
public abstract String getDescription();
}
Milk配料
public class Milk extends CondimentDecorator{
Beverage beverage;
public Milk(Beverage beverage) {
this.beverage = beverage;
}
@Override
public String getDescription() {
return beverage.getDescription()+",牛奶";
}
@Override
public double cost() {
return beverage.cost()+0.1;
}
}
Mocha配料
public class Mocha extends CondimentDecorator {
Beverage beverage;
public Mocha(Beverage beverage) {
this.beverage = beverage;
}
@Override
public String getDescription() {
return beverage.getDescription()+",摩卡";
}
@Override
public double cost() {
return beverage.cost()+0.2;
}
}
Soy配料
public class Soy extends CondimentDecorator{
Beverage beverage;
public Soy(Beverage beverage) {
this.beverage = beverage;
}
@Override
public String getDescription() {
return beverage.getDescription()+",豆?jié){";
}
@Override
public double cost() {
return beverage.cost()+0.15;
}
}
Whip配料
public class Whip extends CondimentDecorator{
Beverage beverage;
public Whip(Beverage beverage) {
this.beverage = beverage;
}
@Override
public String getDescription() {
return beverage.getDescription()+",奶泡";
}
@Override
public double cost() {
return beverage.cost()+0.1;
}
}
測(cè)試類
public class StartbuzzCoffee {
public static void main(String[] args) {
Beverage beverage = new Espresso();
System.out.println(beverage.getDescription()+",$"+beverage.cost());
System.out.println("========================");
Beverage beverage2 = new DarkRoast();
beverage2 = new Mocha(beverage2);
beverage2 = new Mocha(beverage2);
beverage2 = new Whip(beverage2);
System.out.println(beverage2.getDescription()+",$"+beverage2.cost());
}
}
測(cè)試結(jié)果
這是一杯濃縮咖啡,$1.99
========================
這是一杯低咖啡因咖啡,摩卡,摩卡,奶泡,$1.55
總結(jié)
- 裝飾者可以提供比繼承更多的靈活性嵌器。
- 可以通過一種動(dòng)態(tài)的方式來擴(kuò)展一個(gè)對(duì)象的功能五芝,在運(yùn)行時(shí)選擇不同的的裝飾器狮崩,從而實(shí)現(xiàn)不同的行為蛛勉。
- 具體組件類和裝飾類可以獨(dú)立變化,用戶可以根據(jù)自己的需要增加具體的組件類和裝飾類睦柴,原有的代碼無需改變诽凌,負(fù)荷”開閉原則“。
- 但是也會(huì)產(chǎn)生很多的小對(duì)象侣诵,增加了系統(tǒng)的負(fù)責(zé)性狱窘。
- 建議在不影響其他對(duì)象的時(shí)候使用,以動(dòng)態(tài)蘸炸,透明的方式給單個(gè)對(duì)象添加職責(zé)。