iOS設(shè)計(jì)模式之組合模式


大家好久不見喲!忙了一個(gè)月終于可以回歸到設(shè)計(jì)模式了。前幾天肥羊蜀黍在玩室友鵬鵬的電腦,感嘆現(xiàn)在的年輕人真是精力旺盛,代碼寫得牛P就算了,還如此勤奮的學(xué)習(xí)各國文化和語言,他的DEF盤放滿各種學(xué)習(xí)資料,什么”日語學(xué)習(xí)“、”歐美風(fēng)情“、“日韓文化”,我對日韓文化也頗感興趣,于是就點(diǎn)開了看看,怎么包了n層文件夾,點(diǎn)到最后....畫面女人看了臉紅,男人看了血脈噴張。好了,警察叔叔來了,要趕緊溜了,畢竟還是無證駕駛?。?!

一、組合模式的概念

先來一段官方概念:組合多個(gè)對象形成樹形結(jié)構(gòu)以表示“整體-部分”的結(jié)構(gòu)層次。組合模式對單個(gè)對象(即葉子對象)和組合對象(即容器對象)的使用具有一致性。

二、案例實(shí)現(xiàn)

這句官方解釋也是有點(diǎn)抽象,為了能讓大家更好地理解組合模式,今天就以我們非常熟悉的電腦文件作為故事背景?。。」芾砦募臅r(shí)候,我們不難發(fā)現(xiàn),文件夾和文件的關(guān)系就像一棵“樹”,如下圖


文件路徑示例

1、非組合模式演示

看完這個(gè)圖,我們再構(gòu)思一下架構(gòu),此時(shí),鵬鵬一拍桌子說是這樣的,如下圖:


鵬鵬還順帶用5分鐘把代碼寫出來了,然而我陷入了沉思...通常來說,業(yè)務(wù)邏輯關(guān)系相對簡單、類之間的繼承關(guān)系少的時(shí)候可以用上圖的架構(gòu),但如果繼承關(guān)系有n層呢?如果項(xiàng)目有多個(gè)層次節(jié)點(diǎn)呢?如果像鵬鵬那么調(diào)皮喜歡把文件用n個(gè)文件夾包著呢?那咋辦?!此時(shí)的我開始抓狂,進(jìn)而不知所措,想想好像也只能殺個(gè)室友祭天了?。。。ù藭r(shí)鵬鵬在墻角瑟瑟發(fā)抖)

2、組合模式演示

還好組合模式的出現(xiàn)拯救了鵬鵬,組合模式分為安全組合模式和透明組合模式,首先介紹比較常用而且比較推崇的安全組合模式,UML如下圖:

2.1 安全組合模式

看了這個(gè)UML鵬鵬松了口氣,小命得保。工作量看著減少很多,接口沒有了,改為了抽象類,方法直接放在實(shí)現(xiàn)類中,好精簡有木有!用Component基類封裝一些通用的方法和屬性,Composite(整體)和Leaf(部分)繼承基類,分別實(shí)現(xiàn)各自的方法,使有復(fù)雜層次關(guān)系或樹狀結(jié)構(gòu)的架構(gòu)簡化為只有整體和部分兩大塊。接下來看看代碼演示:

Component.h
//通用屬性
@property (nonatomic,copy) NSString *name;
@property (nonatomic,assign) float size;
//通用方法
- (instancetype)initWithName:(NSString *)name andSize:(float)size;
- (NSString *) getInfo;
Component.m
//方法實(shí)現(xiàn)
- (void)addFile:(Component *)file {
    [self.sububdirectory addObject:file];
}

- (NSArray *)getSubdirectory {
    return self.sububdirectory;
}

- (NSMutableArray *)sububdirectory {
    if (!_sububdirectory) {
        _sububdirectory = [NSMutableArray array];
    }
    return _sububdirectory;
}
//使用場景
- (void) compositePattern {
    //d_disk 作為root
    //鵬鵬的D盤學(xué)習(xí)資料最多,我們就來剖析D盤吧...嘻嘻嘻~~wow?。?!1T學(xué)習(xí)資料哦
    Composite *d_disk = [[Composite alloc] initWithName:@"鵬鵬的D盤" andSize:1024];
    //鵬鵬真勤奮,這么多類型的學(xué)習(xí)資料
    //這里暫且忽略中間包的n層文件夾吧
    Composite *language_Jan = [[Composite alloc] initWithName:@"日語學(xué)習(xí)" andSize:0.5];
    Composite *culture_Korea = [[Composite alloc] initWithName:@"韓國風(fēng)俗文化" andSize:0.25];
    //這部小電影...知道文件名叫啥不?so easy...耳熟能詳!跟著蜀黍大聲讀“雅蠛蝶?。?!”
    Leaf *video_Jan = [[Leaf alloc] initWithName:@"やめて" andSize:0.5];
    //其他小電影名字太辣眼睛,這里就不做詳細(xì)介紹(車牌還是找吾力鵬鵬要)
    Leaf *video_Jan1 = [[Leaf alloc] initWithName:@"小電影1" andSize:0.5];
    Leaf *video_Jan2 = [[Leaf alloc] initWithName:@"小電影2" andSize:0.2];
    Leaf *pic_Korea1 = [[Leaf alloc] initWithName:@"小圖片1" andSize:0.02];
    Leaf *pic_Korea2 = [[Leaf alloc] initWithName:@"小圖片2" andSize:0.01];
    //開始組裝樹
    [d_disk addFile:language_Jan];
    [d_disk addFile:culture_Korea];
    [language_Jan addFile:video_Jan];
    [language_Jan addFile:video_Jan1];
    [language_Jan addFile:video_Jan2];
    [culture_Korea addFile:pic_Korea1];
    [culture_Korea addFile:pic_Korea2];
    //遍歷硬盤里面的各個(gè)文件(小電影)
    NSLog(@"%@",[d_disk getInfo]);
    [self cp_traverseSubdiretory:[d_disk getSubdirectory]];
}

- (void) cp_traverseSubdiretory:(NSArray *)directory {
    for (id obj in directory) {
        if ([obj isKindOfClass:[Composite class]]) {
            Composite *folder = obj;
            NSLog(@"%@",[folder getInfo]);
            //遞歸遍歷
            [self cp_traverseSubdiretory:[folder getSubdirectory]];
        }else{
            Leaf *file = obj;
            NSLog(@"%@",[file getInfo]);
        }
    }
}

運(yùn)行結(jié)果如下:

組合模式demo[1295:17972] name:鵬鵬的D盤 | size:1024.0
組合模式demo[1295:17972] name:日語學(xué)習(xí) | size:0.5
組合模式demo[1295:17972] name:やめて | size:0.5
組合模式demo[1295:17972] name:小電影1 | size:0.5
組合模式demo[1295:17972] name:小電影2 | size:0.200000
組合模式demo[1295:17972] name:韓國風(fēng)俗文化 | size:0.25
組合模式demo[1295:17972] name:小圖片1 | size:0.02
組合模式demo[1295:17972] name:小圖片2 | size:0.01

上述就是安全組合模式的簡單演示。接下來就是透明組合模式的介紹。

2.2透明組合模式

透明組合模式和安全組合模式的區(qū)別不大,只有一點(diǎn),Leaf和Composite的方法全部在基類Component實(shí)現(xiàn),UML如下:


由于篇幅問題,透明組合模式的代碼演示就不放啦!

要詳細(xì)了解請到詳細(xì)代碼演示查看

三、總結(jié)分析

1、安全組合模式

  • 優(yōu)點(diǎn):
    安全組合模式是由基類管理通用方法,Leaf和Composite各自管理擁有的方法,能確保各個(gè)類都只有職責(zé)范圍內(nèi)的方法,比如文件夾只會有添加文件的方法,不可能有打開文件的功能,視頻文件也只有播放視頻的功能,不可能有添加文件的功能。
  • 缺點(diǎn):
    在代碼演示部分可以看到,在安全組合模式下需要對類進(jìn)行判斷,如果繼承基類的子類數(shù)目多,就會造成過多if-else的判斷,影響代碼質(zhì)量。如果子類數(shù)量較多的時(shí)候應(yīng)慎重考慮。

2、透明組合模式

  • 優(yōu)點(diǎn):
    在透明組合模式下,由基類統(tǒng)一管理所有方法,因此不需要進(jìn)行類型判斷轉(zhuǎn)換。該模式針對抽象類編程,上層(抽象基類)的調(diào)用不依賴下層(子類),基本遵循依賴倒置原則,方便擴(kuò)展。
  • 缺點(diǎn):
    透明模式的缺點(diǎn)也十分明顯,由于方法由基類統(tǒng)一管理,可能會出現(xiàn)類持有了職責(zé)范圍外的方法,例如一個(gè)文件類具有添加文件夾的方法,這顯然是不合理的,因此在子類中我們會重寫子類不應(yīng)該擁有的方法,通常會重寫為空方法或拋出異常處理,這一定程度上違反了里氏替換原則,還一定程度加大了工作量。
  • 總體來說,組合模式的優(yōu)缺點(diǎn)都十分突出且極端,在使用前要結(jié)合需求進(jìn)行分析,靈活運(yùn)用,盲目套用設(shè)計(jì)模式反而會給自己挖坑哦!
一個(gè)月沒寫文章了,學(xué)習(xí)的同時(shí)一定要懂得總結(jié),而寫作就是一次對自己學(xué)習(xí)結(jié)果的檢驗(yàn),今后要把總結(jié)和寫作作為一種興趣一種習(xí)慣。為自己的目標(biāo)干巴爹!??!
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容