設計模式 裝飾者模式介紹

2021-10-25 02:14:14 字數 3147 閱讀 6240

考慮乙個咖啡店收費的問題:如何實現靈活的咖啡的**計算。 咖啡店主要賣咖啡,但是後來為了滿足不同客戶的不同口味,只是純咖啡,顯得太單調了,就考慮增加不同的搭配,搭配不同的配料後會組成另一種飲品,這樣,品種豐富了,但隨之問題也來了,如何為不同新的品種計算新的準確的**。兩種方案:

第一種:可以採用繼承的方式,將純咖啡作為基類,而後需要什麼品種的話,可以生成乙個子類,單獨作為乙個品種來重寫計算**的方法,並且還可以為這個品種新增其他功能。但是:繼承有乙個很大的問題就是,這樣的方案實現是首先你是知道都有什麼品種的,才會派生出各種子類,但是,如果後續想要在某個現有品種中去掉一些或者加上一些內容,甚至直接刪除這個品種,就會很麻煩的總是修改對應的類了,而且還有個缺點是:會產生很多種子類,如果品種很多,而且每個品種的差別很小的時候,都分別單獨的作為乙個類就會很麻煩。

第二種:就是採用我們今天要講的這篇文章的主題裝飾者模式。先模擬一下生活中的乙個例子:一張紙質的**,想要讓這張**儲存的久一點,我們可以先給這張**塑封;塑封後,覺得還不夠的話,可能還會給這張**裝乙個相框;加乙個相框還覺得不能好好保護相片的話,再加個玻璃罩。在這個例子中,我們可以理解**本身就是要被裝飾的物件,塑封膠、相框、玻璃罩都是作為裝飾者。每一層的裝飾者都不會修改最裡邊的被裝飾的物件。這裡我們可以把具體的咖啡飲品當做被裝飾者,要加入的食物或飲料當做裝飾者,每一種咖啡飲品可以被不同的裝飾者裝飾。

將上述為不同咖啡飲品計算**的問題用程式設計的概念來講就是如何能夠透明地給乙個物件增加功能,並實現功能的動態組合。這就是裝飾者模式的功能。

裝飾者模式能夠實現動態地為物件新增功能,從乙個物件外部透明的給物件增加功能。透明地給乙個物件增加功能,就是說要給乙個物件增加功能,但是不能讓這個物件知道,也就是不能去修改這個物件

每個被裝飾者可以被多個裝飾者裝飾。例如:黑咖啡(被裝飾者)可以被牛奶(裝飾者)、水果(裝飾者)裝飾,而且,不同的裝飾者之間沒有先後順序的限制。

裝飾者需要和被裝飾的物件繼承於同樣的類或者實現同樣的介面(ios中稱遵守同樣的協議),而後,在具體的裝飾者的實現中,轉調被裝飾者物件【這就需要裝飾者物件持有乙個被裝飾者物件】

下邊是具體實現的uml圖和不同類之間的呼叫層次圖。

從上邊的層次圖中可以看出,多層裝飾者一層層的包在被裝飾物件的外部,功能方法的呼叫也是一層層遞迴呼叫被裝飾的物件。從圖中可以看出:當黑咖啡被牛奶裝飾後,牛奶裝飾器就成為了新的被裝飾者,可以被後續的其它裝飾者裝飾,而且各個裝飾者之間是沒有順序要求的。順序完全可以按照自己的意願來進行。

//********************************咖啡元件(基類)*********************

@inte***ce coffeecomponent : nsobject

- (double)getprice;

@end

@implementation coffeecomponent//抽象元件,可以寫預設實現的方法,也可以用協議實現

- (double)getprice

@end

//********************************黑咖啡(具體咖啡類)*********************

@inte***ce blackcoffee : coffeecomponent//繼承於抽象元件的具體元件

- (double)getprice;

@end

@implementation blackcoffee

- (double)getprice

@end

//********************************裝飾者基類*********************

@inte***ce condimentdecorator : coffeecomponent//繼承於元件的裝飾者抽象類

- (instancetype)initwithcomponent:(coffeecomponent *)component;

@property (nonatomic,strong)coffeecomponent *component;

@end

@implementation condimentdecorator

- (instancetype)initwithcomponent:(coffeecomponent *)component

return self;

}@end

//********************************牛奶裝飾者(具體裝飾者)*********************

@inte***ce milkdecorator : condimentdecorator//繼承於抽象佐料裝飾者的具體裝飾者

@end

@implementation milkdecorator

- (double)getprice

@end

//在此省略其它裝飾者的**,與牛奶裝飾者的**一樣。**可以檢視demo。

//*************************外部呼叫********************=

//純咖啡

blackcoffee *blackcoffee = [[blackcoffee alloc]init];

//加奶

milkdecorator *milkdecorator = [[milkdecorator alloc]initwithcomponent:blackcoffee];

//加豆漿

soydecorator *soydecorator = [[soydecorator alloc]initwithcomponent:milkdecorator];

//加水果

fruitdecorator *fruitdecorator = [[fruitdecorator alloc]initwithcomponent:soydecorator];

nslog(@"一共多少錢%f",[fruitdecorator getprice]);

裝飾者模式介紹

裝飾者模式 動態的將新功能附加到物件上。在物件功能擴充套件方面,它比繼承更 有彈性。裝飾者模式就像打包乙個快遞。主體 component 比如 陶瓷 食物 包裝 decorator 比如 報紙 泡沫 1 建立快遞主體抽象類和具體快遞類 public abstract class delivery p...

設計模式 裝飾者模式

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

設計模式 裝飾者模式

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