設計模式 裝飾者模式

2021-06-21 13:27:22 字數 3574 閱讀 7943

沒什麼特別的,之前看懂了,這次自己再複述一下。畢竟把別人講懂了才是真的懂了。主要參考了head first 設計模式。

例子講述的是在為星巴克咖啡的製作訂單的情況,比如客人點了飲料,那麼系統會自動算出**(不知道是我沒有體會到,還是這個例子不太合適,算出**那麼簡單的事還需要用到類?,不過不影響我們思考裝飾者模式)。不過似乎星巴克離普通的中國人還是太遙遠了,我倒可以認為我們想象成中國麵館比較好。

這家中國麵館賣很多種類的面,有我喜歡的哨子面、牛肉麵、雜醬麵、板麵等等面,每乙個面都有**,這是非常正常的。如果每一種面都有乙個**,那麼這個訂單生成系統好像還比較簡單。因為繼承是一種不錯的選擇。下圖直接擷取了head first 設計模式,所以裡面是飲料。那麼飲料就相當於我上面所述的面,而牛肉麵就相當於乙個飲料的一種,比如:dark roast。

問題來了,面還可以加各類配料,比如你說老闆多加乙個雞蛋,另乙個說多加乙個肉丸,多加乙個火腿腸。難道我們為每一種加了配料的面都來實現一種類來計算價錢嗎?如此一來,將會有非常多的類。比如加了雞蛋的牛肉麵、加了肉丸的牛肉麵.....那麼我們的類就繼承就會成為下面這個樣子。

可以看出我們要實現每乙個子類就非常辛苦了,需要自己懂把加了丸子、雞蛋的牛肉麵,提前加一遍算好放在這個子類裡使用。更可怕的是:如果丸子**漲了,怎麼辦?我們又要把所有的有丸子的子類都加一遍嗎?

這是一種可以解決的方案。在父類麵裡面有丸子、雞蛋的布林值,和具體**,那麼使用者在選擇新增了雞蛋的時候,就將雞蛋的布林值改為true,然後再將父類的cost()方法實現為加上所有的配料的**。那麼子類在cost()方法裡面用自己這道麵的**加上父類的cost(),就是配料的**,那麼就算出了總共需要多少錢了。

下圖是偽**,我們可以看出,子類darkroast的cost()方面裡面呼叫了父類的cost()方法,而父類cost()方面,主要是判斷這個訂單有沒有加這個某種配料,加了的話就加上這個配料的**。

然而,這樣做有以下三種情況會使我們很難處理:

如果出現新調料,我們需要改變超類。似乎這樣很不好

某些飲料裡面就不能加某些調料,然而我們並沒有限制

如果某個客戶想要雙倍的調料,則無法處理。

這裡書中:提出了類應該對擴充套件開放,對修改關閉

因為 此時書中引入裝飾者模式,其實我是知道看來了**之後才知道到底是怎麼回事。我的理解就是,所謂裝飾者,其也是繼承於基類(面)的乙個實現類,這個實現類必須有有有乙個成員變數:就是另乙個實現類,也就是被包含的實現類,也就是我們裝飾者所要裝飾的物件。比如牛肉麵就是乙個實現類,他是被裝飾的,可以被加雞蛋這個實現類來修飾,加雞蛋這個實現類的成員變數可以引用牛肉麵,那麼就組成了加雞蛋的牛肉麵,如果其成員變數引用了哨子面,那麼就成了加雞蛋的哨子面。而且,這個加雞蛋的哨子面還可以被加丸子的實現類來裝飾,那麼就是成了加丸子 加雞蛋的牛肉麵。當然,也可以加兩個雞蛋。

所以,我們要把實現類分為兩類,一種實現類時調料,其有乙個成員變數就是基類的乙個物件。另乙個實現類就是面的種類:牛肉麵、哨子面。

我在書上的圖,作了一些額外的說明。如下:

另外書上也給了飲料的圖,更為簡單和清晰些:

實際上我還是覺得**描述的更為清楚:

* 這是乙個面的基類。所以面的種類的實現類和調料的裝飾類都必須繼承這個類。

* @author zy

* */

public abstract class noodle

public abstract double cost();

}

public class beefnoodle extends noodle 

@override

public double cost()

}

public class porknoodle extends noodle 

@override

public double cost()

}

public abstract class condimendecorator extends noodle

public class eggcondiment extends condimendecorator 

@override

public string getdescription()

@override

public double cost()

}

public class meatballcondiment extends condimendecorator 

@override

public string getdescription()

@override

public double cost()

}

牛肉麵:10.0

豬肉面:7.0

牛肉麵加雞蛋:11.0

豬肉麵加雞蛋加肉丸:10.0

如下圖所示:

其中我們可以看出filterinputstream專門作為裝飾者。其實現類linenumberinputstream就可以得到inputstream流中的行數。

書中還舉出了簡單的例子,自己寫了乙個filterinputstream的實現類。也就是裝飾類。有新興趣的看看書吧

比較有趣,不過這些設計模式都需要深刻的體會。懂了其含義只是剛剛開始吧。對了,定義很難理解。所以,一直沒說。

沒有上傳網盤。**比較簡單。

設計模式 裝飾者模式

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

設計模式 裝飾者模式

好幾天沒出部落格了,在學習android的一些新控制項的時候,用到了乙個模式,叫裝飾者模式,所以在此講講這個模式。模式,包含以下四個角色 1 抽象構件 component 角色 給出乙個抽象介面,以規範準備接收附加責任的物件。2 具體構件 concretecomponent 角色 定義乙個將要接收附...

設計模式 裝飾者模式

一 什麼是裝飾者模式 動態地給一些物件新增一些額外的功能。就增加功能來說裝飾者模式比生成子類更加靈活。裝飾者模式是一種物件結構型模式。二 裝飾者模式的優缺點 1 裝飾者模式與 類繼承都是實現功能的擴充套件,但是裝飾者模式比類繼承有更多的靈活性。2 裝飾者模式可以使用具體裝飾類的排列組合,這樣一來可以...