設計模式學習之路 裝飾者模式 動態擴充套件器

2021-07-15 08:05:20 字數 2698 閱讀 7011

今天了解下裝飾者模式。

首先,看下需求。

一家咖啡廳需要做乙個訂單系統,為了配合他們的飲料**需求。

首先有乙個超類,飲料類。

package com.chris.decorator;

public abstract class beverage

public abstract double cost();

}

他有乙個屬性,對飲料的描述,兩個方法,乙個方法是返回描述,另乙個方法是抽象方法, 返回飲料的價錢。

然後我們開始做事了,建立乙個實體類,比如摩卡咖啡,繼承飲料類,然後加上相應的描述並且重寫cost()方法就行了。

每一種飲料都寫乙個類去繼承,比如蒸餾咖啡, 黑咖啡, 拿鐵咖啡等等等等。。

好像看起來沒有什麼問題。

這時候,其他的需求就來了, 購買咖啡的時候,顧客可以要求向咖啡中加入各種調料, 比如蒸奶, 豆漿, 摩卡 或者奶泡等等。

然後我們開始不同的嘗試。

第一種嘗試:

按照上面的思路,我們對每一種不同的咖啡都建立一種新的類,去繼承超類,然後通過返回不同的描述和**,達到我們的目的。

比如:黑咖啡, 加蒸奶的黑咖啡,加摩卡的黑咖啡, 加蒸奶和摩卡的黑咖啡。。。。。等等等等。。。

這時候我們會發現乙個問題了,通過不同的組合,我們必須要窮舉所有的型別,才能把這個系統完善,這就要「類**」了,現實中要維護這麼多同種類是十分可怕而且愚蠢的。

由於第一種方案很low,我們開始考慮其他的方案

第二種嘗試:

我們通過在超類中加屬性,蒸奶,摩卡等等。。然後返回是否需要蒸奶,是否需要摩卡等方法。。

這樣的話,通過設定不同的屬性,我們可以定義出不同的飲料,只需要設定是否需要蒸奶,是否需要摩卡等字段就行了,再通過調料的選擇計算**。

這個方案好像是比上面理智點,只需要基本的飲料類了, 至少不會由於調料的增加再增加新的類。

但是仔細想想, 好像還是有什麼不妥,如果再要加新的調料的話,我們還需要把這個超類屬性和相應的方法也修改。

這就違背了設計模式的乙個重要的原則:類應該對擴充套件開發,對修改關閉。

第三種嘗試:

這裡,我們就開始引入我們的裝飾者模式。

為何叫裝飾者呢,就是因為我們只需要建乙個飲料的物件,就可以用不同的調料去裝飾他,而且可以一層一層的裝飾,

最後呼叫cost()方法,通過依賴委託將調料的**動態的加上去。

如何理解呢,我們直接看**吧,前面的超類已經有了,我就不重複貼**了。

這裡,我們需要加乙個新的裝飾者類---調料類,並且繼承飲料類,他只有乙個抽象方法。

package com.chris.decorator;

public abstract class condiment extends beverage

我們先實現一種咖啡, 濃縮咖啡!

package com.chris.decorator;

public class espresso extends beverage

@override

public double cost()

}

然後我們再實現一種具體的調料,摩卡!

package com.chris.decorator;

public class mocha extends condiment

@override

public string getdescription()

@override

public double cost()

}

調料的實現就比較關鍵了,在調料中,我們會有乙個beverage的屬性,當傳入某種飲料後,會預先處理這種飲料的方法,並返回當前飲料的最後**。

這樣的話,就把調料裝飾了傳入的飲料, 並且可以一層一層的裝飾,並且返回最後的**。

為了測試,我們再加入一種調料,奶泡!

package com.chris.decorator;

public class whip extends condiment

@override

public string getdescription()

@override

public double cost()

}

下面,我們要點一杯濃縮咖啡,再點一杯加了摩卡和奶泡的濃縮咖啡!

package com.chris.decorator;

public class coffeetestdrive

}

再貼下測試結果咯, 錢應該算的清吧,算數應該沒這麼差吧。。

espresso ¥30.0

espresso add mocha add whip ¥38.0

有木有很方便,一下讓**變的優雅起來。

這就是裝飾者模式:動態的將責任附加到物件上,若要擴充套件功能,裝飾者提供了比繼承更有彈性的替代方案。

使用裝飾者模式, 可以讓我們不需要改變原有的**就可以動態的擴充套件新的需求.

在jdk的原始碼中, filterinputstream 和 bufferedinputstream 就是使用的裝飾著模式,通過一層一層的裝飾,將inputstream的功能豐富化.

設計模式學習 裝飾者模式

當我們來到kfc開始點餐的時候,一開始還不是特別有胃口,所以只點了乙份漢堡 有乙份漢堡和飲料,但後來又點了乙份薯條,最後乾脆再點乙份炸雞腿,那麼如何來計算我們花了多少錢呢?在這個場景下,裝飾者模式會起到很好的效果。定義 動態的將責任附加到物件身上。若要擴充套件功能,裝飾者提供了比繼承更有彈性的替代方...

設計模式 裝飾者模式

public abstract class beverage public abstract double cost public abstract class condimentdecorator extends beverage public class darkroast extends be...

設計模式 裝飾者模式

沒什麼特別的,之前看懂了,這次自己再複述一下。畢竟把別人講懂了才是真的懂了。主要參考了head first 設計模式。例子講述的是在為星巴克咖啡的製作訂單的情況,比如客人點了飲料,那麼系統會自動算出 不知道是我沒有體會到,還是這個例子不太合適,算出 那麼簡單的事還需要用到類?不過不影響我們思考裝飾者...