組合模式(Composite)

?基本概念

組合模式(Composite)拍埠,將對象組合成樹形結(jié)構(gòu)以表示‘部分-整體’的層次結(jié)構(gòu)。組合模式使得用戶對單個對象和組合的對象的使用具有了一致性砚婆。


component為組合中的對象聲明接口械拍,在適當情況下,實現(xiàn)所有類共有接口的默認行為装盯。

leaf在組合中表示葉節(jié)點對象坷虑,葉節(jié)點沒有子節(jié)點。

composite定義有子節(jié)點埂奈,用來存儲字部分迄损,在component接口中實現(xiàn)與字部分有關(guān)的操作。


代碼實現(xiàn)


公司類抽象

@interface Company : NSObject

@property (nonatomic, copy)NSString *name;

@property (nonatomic, strong)NSMutableArray *childrenArray;

- (instancetype)initWithName:(NSString *)name;

- (void)add:(Company *)company;

- (void)remove:(Company *)company;

- (void)display:(int)depth;//顯示

- (void)lineOfDuty;// 履行職責(zé)

#import "Company.h"

@interface Company()

@end

@implementation Company

- (instancetype)initWithName:(NSString *)name

{

self = [super init];

if (self) {

self.name = name;

self.childrenArray = [NSMutableArray array];

}

return self;

}

具體公司類

#import "ConcreteCompany.h"

@implementation ConcreteCompany

- (void)add:(Company *)company

{

[self.childrenArray addObject:company];

}

- (void)remove:(Company *)company

{

if ([self.childrenArray containsObject:company]) {

[self.childrenArray removeObject:company];

}

}

- (void)display:(int)depth

{

NSLog(@"%d-%@",depth,self.name);

for (Company *component in self.childrenArray) {

[component display:(depth + 2)];

}

}

- (void)lineOfDuty

{

for (Company *component in self.childrenArray) {

[component lineOfDuty];

}

}

@end

人力資源部和財務(wù)部

(1)人力

#import "HRDepartment.h"

@implementation HRDepartment

- (void)add:(Company *)company

{

}

- (void)remove:(Company *)company

{

}

- (void)display:(int)depth

{

NSLog(@"%d-%@",depth,self.name);

}

- (void)lineOfDuty

{

NSLog(@"%@ 員工招聘培訓(xùn)管理",self.name);

}

@end

(財務(wù))

#import "FinanceDepartment.h"

@implementation FinanceDepartment

- (void)add:(Company *)company

{

}

- (void)remove:(Company *)company

{

}

- (void)display:(int)depth

{

NSLog(@"%d-%@",depth,self.name);

}

- (void)lineOfDuty

{

NSLog(@"%@ 公司財務(wù)收支管理",self.name);

}

@end

客戶端調(diào)用

ConcreteCompany *root = [[ConcreteCompany alloc] initWithName:@"北京總公司"];

[root add:[[HRDepartment alloc]initWithName:@"總公司人力資源部"]];

[root add:[[FinanceDepartment alloc]initWithName:@"總公司財務(wù)部"]];

ConcreteCompany *comp = [[ConcreteCompany alloc] initWithName:@"上海華東分公司"];

[comp add:[[HRDepartment alloc]initWithName:@"華東分公司人力資源部"]];

[comp add:[[FinanceDepartment alloc]initWithName:@"華東分公司財務(wù)部"]];

[root add:comp];

ConcreteCompany *comp1 = [[ConcreteCompany alloc] initWithName:@"南京辦事處"];

[comp1 add:[[HRDepartment alloc]initWithName:@"南京辦事處人力資源部"]];

[comp1 add:[[FinanceDepartment alloc]initWithName:@"南京辦事處財務(wù)部"]];

[comp add:comp1];

ConcreteCompany *comp2 = [[ConcreteCompany alloc] initWithName:@"杭州辦事處"];

[comp2 add:[[HRDepartment alloc]initWithName:@"杭州辦事處人力資源部"]];

[comp2 add:[[FinanceDepartment alloc]initWithName:@"杭州辦事處財務(wù)部"]];

[comp add:comp2];

[root display:1];

[root lineOfDuty];

輸出

2017-04-28 10:56:51.191 PlayTry[1942:63351] 1-北京總公司

2017-04-28 10:56:51.191 PlayTry[1942:63351] 3-總公司人力資源部

2017-04-28 10:56:51.192 PlayTry[1942:63351] 3-總公司財務(wù)部

2017-04-28 10:56:51.192 PlayTry[1942:63351] 3-上海華東分公司

2017-04-28 10:56:51.192 PlayTry[1942:63351] 5-華東分公司人力資源部

2017-04-28 10:56:51.193 PlayTry[1942:63351] 5-華東分公司財務(wù)部

2017-04-28 10:56:51.193 PlayTry[1942:63351] 5-南京辦事處

2017-04-28 10:56:51.193 PlayTry[1942:63351] 7-南京辦事處人力資源部

2017-04-28 10:56:51.193 PlayTry[1942:63351] 7-南京辦事處財務(wù)部

2017-04-28 10:56:51.194 PlayTry[1942:63351] 5-杭州辦事處

2017-04-28 10:56:51.194 PlayTry[1942:63351] 7-杭州辦事處人力資源部

2017-04-28 10:56:51.194 PlayTry[1942:63351] 7-杭州辦事處財務(wù)部

2017-04-28 10:56:51.195 PlayTry[1942:63351] 總公司人力資源部 員工招聘培訓(xùn)管理

2017-04-28 10:56:51.195 PlayTry[1942:63351] 總公司財務(wù)部 公司財務(wù)收支管理

2017-04-28 10:56:51.196 PlayTry[1942:63351] 華東分公司人力資源部 員工招聘培訓(xùn)管理

2017-04-28 10:56:51.222 PlayTry[1942:63351] 華東分公司財務(wù)部 公司財務(wù)收支管理

2017-04-28 10:56:51.224 PlayTry[1942:63351] 南京辦事處人力資源部 員工招聘培訓(xùn)管理

2017-04-28 10:56:51.224 PlayTry[1942:63351] 南京辦事處財務(wù)部 公司財務(wù)收支管理

2017-04-28 10:56:51.226 PlayTry[1942:63351] 杭州辦事處人力資源部 員工招聘培訓(xùn)管理

2017-04-28 10:56:51.226 PlayTry[1942:63351] 杭州辦事處財務(wù)部 公司財務(wù)收支管理

總結(jié)

將 對 象 組 合 成 樹 形 結(jié) 構(gòu) 以 表 示 “ 部 分 -整 體 ” 的 層 次 結(jié) 構(gòu) 账磺。 組合模式 使 得 用 戶 對 單 個 對 象 和組合對象的使用具有一致性芹敌。

組合模式的目的就是讓客戶端不用區(qū)分操作的對象是子節(jié)點還是葉節(jié)點,而是用一種統(tǒng)一的方式來操作垮抗。

實現(xiàn)這個目標的關(guān)鍵在于氏捞,設(shè)計一個抽象的組件類,讓它可以代碼子節(jié)點和葉節(jié)點冒版,這樣客戶端就不需要區(qū)分二者液茎,統(tǒng)一操作它們即可。

通常辞嗡,組合模式都是用樹形結(jié)構(gòu)來表示的捆等,通過根節(jié)點、子節(jié)點续室、葉節(jié)點組合成一顆對象樹栋烤,這也意味著任何可以使用對象樹來描述或者操作的功能,都可以使用組合模式來進行挺狰,比如XML解析明郭,層次結(jié)構(gòu)的菜單买窟,iOS中由多個子視圖構(gòu)成的復(fù)雜視圖,這些都可以使用組合模式來實現(xiàn)达址。

同時要注意蔑祟,因為要讓客戶端統(tǒng)一操作子節(jié)點和葉節(jié)點趁耗,那么他們的抽象類就必須定義包含二者的所有方法沉唠,如果調(diào)用者調(diào)用了它們不支持的方法,可以拋出異常警告苛败。這雖然違反了單一原則满葛,但是在實際開發(fā)中是合理的。

好處

定義了包含基本對象和組合對象的類層次結(jié)構(gòu)

基本對象可以被組合成更復(fù)雜的組合對

象,而這個組合對象又可以被組合,這樣不斷的遞歸下去罢屈∴秩停客戶代碼中,任何用到基本

對象的地方都可以使用組合對象。

簡化客戶代碼

客戶可以一致地使用組合結(jié)構(gòu)和單個對象缠捌。通常用戶不知道 (也不關(guān)心)處理的是一個葉節(jié)點還是一個組合組件锄贷。這就簡化了客戶代碼 , 因為在定義組合的那些類中不需要寫一些充斥著選擇語句的函數(shù)。

使 得 更 容 易 增 加 新 類 型 的 組 件

新定義的 C o m p o s i t e 或 L e a f 子 類 自 動 地 與 已 有 的 結(jié) 構(gòu) 和 客

戶代碼一起工作,客戶程序不需因新的 C o m p o n e n t類而改變曼月。

使你的設(shè)計變得更加一般化

容易增加新組件也會產(chǎn)生一些問題,那就是很難限制組合

中的組件谊却。有時你希望一個組合只能有某些特定的組件。使用 C o m p o s i t e 時,你不能依賴類型系統(tǒng)施加這些約束,而必須在運行時刻進行檢查哑芹。

使用時機

如果你想表示對象的部分--整體層次結(jié)構(gòu)炎辨。可以選用組合模式把整體和部分統(tǒng)一起來聪姿,使得層次結(jié)構(gòu)實現(xiàn)更簡單碴萧,從外部使用這個層次結(jié)構(gòu)也更容易。

如果你希望統(tǒng)一的使用組合結(jié)構(gòu)中的所有對象末购,這正是組合模式提供的主要功能

參考文章

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末破喻,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子盟榴,更是在濱河造成了極大的恐慌曹质,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,997評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件曹货,死亡現(xiàn)場離奇詭異咆繁,居然都是意外死亡,警方通過查閱死者的電腦和手機顶籽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評論 3 392
  • 文/潘曉璐 我一進店門玩般,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人礼饱,你說我怎么就攤上這事坏为【柯浚” “怎么了?”我有些...
    開封第一講書人閱讀 163,359評論 0 353
  • 文/不壞的土叔 我叫張陵匀伏,是天一觀的道長洒忧。 經(jīng)常有香客問我,道長够颠,這世上最難降的妖魔是什么熙侍? 我笑而不...
    開封第一講書人閱讀 58,309評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮履磨,結(jié)果婚禮上蛉抓,老公的妹妹穿的比我還像新娘。我一直安慰自己剃诅,他們只是感情好巷送,可當我...
    茶點故事閱讀 67,346評論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著矛辕,像睡著了一般笑跛。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上聊品,一...
    開封第一講書人閱讀 51,258評論 1 300
  • 那天飞蹂,我揣著相機與錄音,去河邊找鬼杨刨。 笑死晤柄,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的妖胀。 我是一名探鬼主播芥颈,決...
    沈念sama閱讀 40,122評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼赚抡!你這毒婦竟也來了爬坑?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,970評論 0 275
  • 序言:老撾萬榮一對情侶失蹤涂臣,失蹤者是張志新(化名)和其女友劉穎盾计,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體赁遗,經(jīng)...
    沈念sama閱讀 45,403評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡署辉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,596評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了岩四。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片哭尝。...
    茶點故事閱讀 39,769評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖剖煌,靈堂內(nèi)的尸體忽然破棺而出材鹦,到底是詐尸還是另有隱情逝淹,我是刑警寧澤,帶...
    沈念sama閱讀 35,464評論 5 344
  • 正文 年R本政府宣布桶唐,位于F島的核電站栅葡,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏尤泽。R本人自食惡果不足惜欣簇,卻給世界環(huán)境...
    茶點故事閱讀 41,075評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望安吁。 院中可真熱鬧醉蚁,春花似錦、人聲如沸鬼店。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽妇智。三九已至,卻和暖如春氏身,著一層夾襖步出監(jiān)牢的瞬間巍棱,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評論 1 269
  • 我被黑心中介騙來泰國打工蛋欣, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留航徙,地道東北人。 一個月前我還...
    沈念sama閱讀 47,831評論 2 370
  • 正文 我出身青樓陷虎,卻偏偏與公主長得像到踏,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子尚猿,可洞房花燭夜當晚...
    茶點故事閱讀 44,678評論 2 354

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