2019-03-06 學(xué)習(xí)iOS設(shè)計(jì)模式二:裝飾者模式

再講具體內(nèi)容之前我們先看一個(gè)《Head First 設(shè)計(jì)模式》里舉的星巴克訂單的例子散休,星巴克提供不同種類的咖啡和咖啡的調(diào)料栋齿,星巴克需要一些類來描述他們并且能計(jì)算出任意一種咖啡和任意幾種調(diào)料搭配在一起的價(jià)格覆山,如果我們用繼承為每一種搭配寫一個(gè)類的話,那就會(huì)有N多個(gè)類,如下圖:


看到上面的類圖瞬間真?zhèn)€人都不好了,是不是后悔選擇了程序員這個(gè)行業(yè)狮杨,不要急,我們可以使用裝飾者模式來讓您的心情陽(yáng)光起來到忽。你也許會(huì)想到可以建了一個(gè)父類橄教,把coffee的配料都寫在里面,然后不同的coffee繼承父類喘漏,這種方式比上面確實(shí)要好护蝶,不過帶來很多數(shù)據(jù)冗余,因?yàn)楦割惖呐淞喜皇敲糠Ncoffee都需要的陷遮。

使用裝飾者模式后滓走,上面的咖啡例子的UML圖如下:


裝飾者模式通過組合的方式擴(kuò)展對(duì)象的特性垦江,這種方式允許我們?cè)谌魏螘r(shí)候?qū)?duì)象的功能進(jìn)行擴(kuò)展帽馋,甚至是運(yùn)行時(shí)擴(kuò)展,面向?qū)ο蟮脑O(shè)計(jì)有原則二是對(duì)擴(kuò)展開放比吭,對(duì)修改關(guān)閉绽族,裝飾者模式就很好的遵循了該原則。裝飾者模式具有一些特征:

1.裝飾者(decorator)和被裝飾(擴(kuò)展)的對(duì)象有著相同的超類(supertype)衩藤。

2.我們可以用多個(gè)裝飾者去裝飾一個(gè)對(duì)象吧慢。

3.我們可以用裝飾過的對(duì)象替換代碼中的原對(duì)象,而不會(huì)出問題(因?yàn)樗麄冇邢嗤某悾?/p>

4.裝飾者可以在委托(delegate赏表,即調(diào)用被裝飾的類的成員完成一些工作)被裝飾者的行為完成之前或之后加上他自己的行為检诗。

5.一個(gè)對(duì)象能在任何時(shí)候被裝飾匈仗,甚至是運(yùn)行時(shí)。

上面來自https://www.cnblogs.com/coffeeSS/p/5405787.html逢慌,具體大家可以進(jìn)去看悠轩。

裝飾者的UML圖如下:


Component:一般是抽象類,在iOS中可以使用類攻泼,也可以使用protocol實(shí)現(xiàn)火架,定義一些接口。

ConcreteComponetA:被修者A忙菠, iOS中繼承Component類或者遵循Component協(xié)議

ConcreteComponetB:被修者B何鸡,同被修飾者A,可以有多個(gè)被修飾者

Decorator:?iOS中繼承Component類或者遵循Component協(xié)議牛欢,裝飾者共同的父類

ConcreteDecoratorA:裝飾者A骡男,用來裝飾ConcreteComponetA或者ConcreteComponetB

ConcreteDecoratorB:裝飾者B,同裝飾者A

下面我們來看一個(gè)吃火鍋的例子傍睹,火鍋有紅鍋和鴛鴦鍋兩種洞翩,每種火鍋又可以添加不同的菜,最終的價(jià)格根據(jù)火鍋的種類和菜的種類來計(jì)算價(jià)格焰望。如果使用裝飾者模式代碼如下:

1.定義Component:使用協(xié)議來實(shí)現(xiàn)

@protocolHuoGuoProtocol

@optional

- (NSString*)getDesc;

- (double)getPrice;

@end

2.定義被被修飾者ConcreteComponetA紅鍋:

#import "HuoGuoProtocol.h"

@interface HongGuo : NSObject<HuoGuoProtocol>

- (instancetype)initWithType:(NSString*)type;

@end


@interface HongGuo()

@property (nonatomic, copy) NSString *type;

@end

@implementation HongGuo

- (instancetype)initWithType:(NSString*)type

{

? ? self= [superinit];

? ? if(self) {

? ? ? ? _type= type;

? ? }


? ? return self;

}

- (NSString*)getDesc

{

? ? return [NSString stringWithFormat:@"%@(%lf)",self.type,[self getPrice]];

}

- (double)getPrice

{

? ? return 30.0;

}

@end

3.定義被被修飾者ConcreteComponetB鴛鴦鍋:

#import "HuoGuoProtocol.h"

@interfaceYuanYangGuo :NSObject

- (instancetype)initWithType:(NSString*)type;

@end

#import "YuanYangGuo.h"

@interface YuanYangGuo()

@property (nonatomic, copy) NSString *type;

@end

@implementation YuanYangGuo

- (instancetype)initWithType:(NSString*)type

{

? ? self= [superinit];

? ? if(self) {

? ? ? ? _type= type;

? ? }


? ? return self;

}

- (NSString*)getDesc

{

? ? return [NSString stringWithFormat:@"%@(%lf)",self.type,[self getPrice]];

}

- (double)getPrice

{

? ? return 50;

}

@end

4.定義Decorator:使用類來實(shí)現(xiàn)骚亿,遵循第一步的協(xié)議

#import "HuoGuoProtocol.h"

@interfaceHuoGuoDecorator :NSObject

@property (nonatomic, weak) id<HuoGuoProtocol> huoGuoObj;

- (instancetype)initWithHuoObj:(id)obj;

@end

#import "HuoGuoDecorator.h"

@implementationHuoGuoDecorator

- (instancetype)initWithHuoObj:(id)obj

{

? ? self= [superinit];


? ? if(self) {

? ? ? ? _huoGuoObj= obj;

? ? }


? ? return self;

}

- (NSString*)getDesc

{

? ? return [self.huoGuoObj getDesc];

}

- (double)getPrice

{

? ? if (self.huoGuoObj)

? ? {

?? ? return[self.huoGuoObjgetPrice];

? ? }


? ? return 0;

}

@end

5.定義裝飾者ConcreteDecoratorA豆腐

@interface DouFu : HuoGuoDecorator

@end

#import "DouFu.h"

@implementation DouFu

- (NSString*)getDesc

{

? ? return [NSString stringWithFormat:@"%@+%@(%lf)",[self.huoGuoObj getDesc],@"豆腐",5.0];

}

- (double)getPrice

{

? ? return[self.huoGuoObjgetPrice] +5;

}

@end

6.同理定義裝飾者ConcreteDecoratorB,ConcreteDecoratorC牛肉和土豆

7.調(diào)用

? ? id<HuoGuoProtocol> hongGuo = [[HongGuo alloc] initWithType:@"紅鍋"];

? // ?id<HuoGuoProtocol> hongGuo = [[YuanYangGuo alloc] initWithType:@"鴛鴦鍋"];

? ? HuoGuoDecorator*decorator = [[HuoGuoDecoratoralloc]initWithHuoObj:hongGuo];

? ? DouFu*doufu = [[DouFualloc]init];

? ? doufu.huoGuoObj= decorator;

? ? Niurou*niuRou = [[Niuroualloc]init];

? ? niuRou.huoGuoObj= doufu;

? ? TuDou*tudou = [[TuDoualloc]init];

? ? tudou.huoGuoObj= niuRou;

? ? typeLabel.text= [tudougetDesc];

? ? priceLabel.text= [NSStringstringWithFormat:@"price:%lf",[tudougetPrice]];

代碼見:https://github.com/steven2008/DesignPattens.git

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市熊赖,隨后出現(xiàn)的幾起案子来屠,更是在濱河造成了極大的恐慌,老刑警劉巖震鹉,帶你破解...
    沈念sama閱讀 218,451評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件俱笛,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡传趾,警方通過查閱死者的電腦和手機(jī)迎膜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來浆兰,“玉大人磕仅,你說我怎么就攤上這事◆こ剩” “怎么了榕订?”我有些...
    開封第一講書人閱讀 164,782評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)蜕便。 經(jīng)常有香客問我劫恒,道長(zhǎng),這世上最難降的妖魔是什么轿腺? 我笑而不...
    開封第一講書人閱讀 58,709評(píng)論 1 294
  • 正文 為了忘掉前任两嘴,我火速辦了婚禮丛楚,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘憔辫。我一直安慰自己鸯檬,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,733評(píng)論 6 392
  • 文/花漫 我一把揭開白布螺垢。 她就那樣靜靜地躺著喧务,像睡著了一般。 火紅的嫁衣襯著肌膚如雪枉圃。 梳的紋絲不亂的頭發(fā)上功茴,一...
    開封第一講書人閱讀 51,578評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音孽亲,去河邊找鬼坎穿。 笑死,一個(gè)胖子當(dāng)著我的面吹牛返劲,可吹牛的內(nèi)容都是我干的玲昧。 我是一名探鬼主播,決...
    沈念sama閱讀 40,320評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼篮绿,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼孵延!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起亲配,我...
    開封第一講書人閱讀 39,241評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤尘应,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后吼虎,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體犬钢,經(jīng)...
    沈念sama閱讀 45,686評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,878評(píng)論 3 336
  • 正文 我和宋清朗相戀三年思灰,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了玷犹。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,992評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡洒疚,死狀恐怖歹颓,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情拳亿,我是刑警寧澤晴股,帶...
    沈念sama閱讀 35,715評(píng)論 5 346
  • 正文 年R本政府宣布愿伴,位于F島的核電站肺魁,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏隔节。R本人自食惡果不足惜鹅经,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,336評(píng)論 3 330
  • 文/蒙蒙 一寂呛、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧瘾晃,春花似錦贷痪、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至强胰,卻和暖如春舱沧,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背偶洋。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工熟吏, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人玄窝。 一個(gè)月前我還...
    沈念sama閱讀 48,173評(píng)論 3 370
  • 正文 我出身青樓牵寺,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親恩脂。 傳聞我的和親對(duì)象是個(gè)殘疾皇子帽氓,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,947評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容