Java设计模式——装饰者模式
概述
本章可以稱為“給愛用繼承的人一個全新的設計眼界”。我們即將再度探討典型濫用問題。你將在本章學到如何使用對象組合的方式,做到在運行時裝飾類。為什么呢?一旦你熟悉了裝飾者的技巧,你將能夠在不修改任何底層代碼的情況下,給你的(或別人的)對象賦予新的職責。
?????????????????????????????????????????????????????????????????????????? ——《Head First 設計模式》
版權說明
著作權歸作者所有。
商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
本文作者:Q-WHai
發表日期: 2015年5月25日
本文鏈接:http://blog.csdn.net/lemon_tree12138/article/details/45870027
來源:CSDN
更多內容:分類 >> 設計模式
使用環境
當我們有多種類型的事物,且每一種事物下面又有很多小的、細的分類。這些分類之間可以隨意組合時(例如一種飲料有一個主原料和一些配料、一道菜會有一個主原料加上一些配料或是去裝飾一個房間等等),我們就可以想一下是不是可以用裝飾模式來實現。下面就《Head First 設計模式》中的例子星巴茲的咖啡說簡單說明一下。
定義
裝飾者模式動態地將責任附加到對象上。若要擴展功能,裝飾者提供了比繼承更有彈性的替代方案。
功能優點
利用組合維護代碼,通過動態地組合對象,可以寫新的代碼添加新功能,而無須修改現有代碼。
?
思路分析
? 在星巴茲的咖啡店里,有多種咖啡,和多種調料。如果我們選擇一種咖啡另外配上一種或是幾種配料(主要主是一個被裝飾者和多個裝飾者)。那么我們如何對這些咖啡和配料進行收費呢(這里采用收費是一個好的舉例,當然也可以是其他的一些相同的事件)?如果你說我們對每一種可選搭配可以封裝,天吶,那該會有多少個類啊。還有一點就是,如果咖啡店里如果有一種咖啡或是配料價格有變動,或是需要新添加一種咖啡或是配料,又該怎么辦呢?
? 其實本文的模式就有一種很好的解決辦法:我們不再使用繼承,因為繼承可能會導致類爆炸的。我們試想一下,能不能把咖啡店中的的所有原料(包括主原料和所有配料)都看成是一種東西(原料)。這樣我們就可以在相互組合的過程中動態實現某些功能。可能你會問為什么要把其看成是一種東西,這樣做的目的是為了在所有原料中實現同一功能,且無關代碼中的組合順序。
?
類圖展示
這里為了方便起見,只繪制出了一部分內容,略去了一些重復或無關痛癢的部分。
當然,你也可以把上面咖啡那4個類再封一層。這里我就書中的內容做了一個原樣輸出。
從類圖中可以看到 Milk 類持有了一個 Beverage 的引用。而對于 Beverage 而言是一個抽象類,正常的咖啡類都要繼承自這個類。也就是說裝飾者類 Milk 持有了全部的咖啡類,通過這樣一層的聚合,這里的 Milk 類就可以對原先的 DarkRoast 類進行包裝裝飾。
代碼展示
Beverage.java
public abstract class Beverage {public String mDescription = "UnKnown Beverage";private int size = 0;public String getDescription() {return mDescription;}public int getSize() {return size;}public void setSize(int size) {this.size = size;}public abstract double cost(); } CondimentDecorator.java
public abstract class CondimentDecorator extends Beverage {@Overridepublic double cost() {return 0;}public abstract String getDescription(); } DarkRoast.java
public class DarkRoast extends Beverage {private double mCost = 0.99;public DarkRoast() {mDescription = "Dark Roast Coffee";}@Overridepublic double cost() {return mCost;}} Milk.java
public class Milk extends CondimentDecorator {private Beverage mBeverage = null;private double mCost = 0.10;public Milk(Beverage beverage) {mBeverage = beverage;}@Overridepublic String getDescription() {return mBeverage.getDescription() + ", Milk";}public double cost() {return mCost + mBeverage.cost();}} StarbuzzCoffee.java
public class StarbuzzCoffee {public static void main(String[] args) {Beverage beverage = new Espresso();System.out.println(beverage.getDescription() + " $" + beverage.cost());Beverage beverage2 = new DarkRoast();beverage2 = new Mocha(beverage2);beverage2 = new Mocha(beverage2);beverage2 = new Whip(beverage2);System.out.println(beverage2.getDescription() + " $" + beverage2.cost());Beverage beverage3 = new HouseBlend();beverage3 = new Soy(beverage3);beverage3 = new Mocha(beverage3);beverage3 = new Whip(beverage3);System.out.println(beverage3.getDescription() + " $" + beverage3.cost());} }
運行圖例
源碼下載
https://github.com/William-Hai/DesignPatternCollections
總結
以上是生活随笔為你收集整理的Java设计模式——装饰者模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android代码混淆及反编译
- 下一篇: Java设计模式——单件模式