定義:
在不改變原有對象的基礎(chǔ)之上语婴,將功能附加到對象上,提供了比繼承更有彈性的替代方案溶握。
適用于:
- 拓展一個(gè)類的功能杯缺;
- 動態(tài)給對象添加功能,并且動態(tài)撤銷奈虾。
優(yōu)點(diǎn):
- 繼承的有力補(bǔ)充夺谁,不改變原有對象的情況下給對象拓展功能廉赔;
- 通過使用不同的裝飾類肉微、不同的組合方式,實(shí)現(xiàn)不同的效果蜡塌。
- 符合開閉原則碉纳。
缺點(diǎn):
- 增加程序復(fù)雜性;
舉個(gè)水果沙拉的例子馏艾。
比如在點(diǎn)水果沙拉外賣時(shí)劳曹,可以往水果沙拉里加各種水果,價(jià)格也會相應(yīng)的調(diào)整琅摩,要讓程序支持不同水果自由組合铁孵,并計(jì)算相應(yīng)的價(jià)格,則可以使用裝飾者模式來完成房资。
定義一個(gè)抽象的水果沙拉類AbstractFruitSalad:
public abstract class AbstractFruitSalad {
public abstract String remark();
public abstract int price();
}
包含備注和價(jià)格抽象方法蜕劝。
接著創(chuàng)建一個(gè)抽象的裝飾器AbstractDecorator(關(guān)鍵點(diǎn),繼承抽象水果沙拉類):
public class AbstractDecorator extends AbstractFruitSalad{
private AbstractFruitSalad fruitSalad;
public AbstractDecorator(AbstractFruitSalad fruitSalad){
this.fruitSalad = fruitSalad;
}
@Override
public String remark() {
return fruitSalad.remark();
}
@Override
public int price() {
return fruitSalad.price();
}
}
創(chuàng)建具體的水果沙拉類FruitSalad:
public class FruitSalad extends AbstractFruitSalad{
@Override
public String remark() {
return "水果??(標(biāo)準(zhǔn))\n";
}
@Override
public int price() {
return 9;
}
}
該沙拉是標(biāo)準(zhǔn)的水果沙拉,價(jià)格是9元岖沛。
如果我們的水果沙拉還允許客戶添加獼猴桃和西瓜暑始,那么我們可以添加兩個(gè)新的裝飾器。添加獼猴桃裝飾器KiwiDecorator:
public class KiwiDecorator extends AbstractDecorator {
public KiwiDecorator(AbstractFruitSalad fruitSalad) {
super(fruitSalad);
}
@Override
public String remark() {
return super.remark() + "加份??切\(zhòng)n";
}
@Override
public int price() {
return super.price() + 2;
}
}
可以看到婴削,加一份獼猴桃需要在原有基礎(chǔ)上加2元廊镜。
接著繼續(xù)創(chuàng)建西瓜裝飾器WaterMelonDecorator:
public class WaterMelonDecorator extends AbstractDecorator {
public WaterMelonDecorator(AbstractFruitSalad fruitSalad) {
super(fruitSalad);
}
@Override
public String remark() {
return super.remark() + "加份??切\(zhòng)n";
}
@Override
public int price() {
return super.price() + 3;
}
}
最后創(chuàng)建客戶端Application測試一下:
public class Application {
public static void main(String[] args) {
// 點(diǎn)了份水果沙拉,并加了兩份??和一份??唉俗,看看最終價(jià)格是多少嗤朴?
AbstractFruitSalad fruitSalad = new FruitSalad();
fruitSalad = new KiwiDecorator(fruitSalad);
fruitSalad = new KiwiDecorator(fruitSalad);
fruitSalad = new WaterMelonDecorator(fruitSalad);
System.out.println(fruitSalad.remark() + "價(jià)格是:" + fruitSalad.price());
}
}
上面的寫法也可以改為:
public class Application {
public static void main(String[] args) {
// 點(diǎn)了份水果沙拉,并加了兩份??和一份??虫溜,看看最終價(jià)格是多少播赁?
AbstractFruitSalad fruitSalad = new FruitSalad();
fruitSalad = new WaterMelonDecorator(new KiwiDecorator(new KiwiDecorator(fruitSalad)));
System.out.println(fruitSalad.remark() + "價(jià)格是:" + fruitSalad.price());
}
}
程序輸出如下:
水果??(標(biāo)準(zhǔn))
加份??切
加份??切
加份??切
價(jià)格是:16
通過不同的裝飾器自由組合,我們可以靈活的組裝出各式各樣的水果沙拉吼渡,這正是裝飾者模式的優(yōu)點(diǎn)容为,但明顯可以看出代碼變復(fù)雜了。
這個(gè)例子的UML圖如下所示: