定義
迭代器模式
提供一種方法順序訪問一個聚合
對象中的各個元素,而又不暴露其內(nèi)部的表示.
組合模式
允許你將對象組合成樹形
來表現(xiàn)"整體/部分"的層次結(jié)構(gòu).組合能讓客戶以一致
的方式處理個別對象和對象組合.
要點
- 迭代器允許訪問聚合的元素,而不需要暴露他的內(nèi)部結(jié)構(gòu).
- 迭代器將遍歷聚合的工作封裝進一個對象中.
- 當(dāng)使用迭代器的時候,我們依賴聚合提供遍歷.
- 迭代器提供了一個通用的接口,讓我們遍歷聚合的項,當(dāng)我們的編碼使用聚合的項時,就可以使用多態(tài)機制.
- 我們應(yīng)該努力讓一個類只分配一個責(zé)任.
- 組合模式提供一個結(jié)構(gòu),可同時包容個別對象和組合對象.
- 組合模式允許客戶對個別對象以及組合對象一視同仁.
- 組合結(jié)構(gòu)內(nèi)的任意對象稱為組件,組件可以是組合,也可以是葉節(jié)點.
- 在實現(xiàn)組合模式時,有許多設(shè)計上的初衷.你要根據(jù)需要平衡透明性和安全性.
個人理解
迭代器模式
書中的各種不同菜單的數(shù)據(jù)存儲集合
調(diào)用的時候確實頗為困難,我在前面學(xué)習(xí)設(shè)計的時候?qū)W習(xí)到了很多設(shè)計原則
,其中很重要的有一點面向接口開發(fā),而不是面向?qū)崿F(xiàn)開發(fā)!
那么如何寫才能使我們的上層調(diào)用變得既簡單,可維護性又高呢?
前期作者僅僅是針對集合
這一個方面來闡述他的設(shè)計理念,如何讓上層調(diào)用者不用考慮菜單集合
的具體實現(xiàn),同時又能夠提高可擴展性來實現(xiàn)功能呢?作者給出了迭代器
這個答案,JAVA
中許多集合實際上是自身實現(xiàn)了迭代器的,這樣的做法其實在我看來,迭代器
就相當(dāng)于使用適配器模式
將菜單
的接口進行統(tǒng)一的適配,方便上層進行調(diào)用.
更深層次的看下去,這樣的做法其實將上層(侍者)
和菜單
進行了解耦
,上層根本不知道菜單是如何實現(xiàn)的
,同時侍者在創(chuàng)建迭代器的時候其實也利用了多態(tài)
,我們后期維護的時候在一定修改范圍內(nèi)這個模式是沒有問題的,但例如在菜單中插入子菜單
那單單依靠迭代器模式已經(jīng)無法滿足需求了,下面我們來看看組合模式.
組合模式
組合模式利用下圖的這種樹形
結(jié)構(gòu),這種結(jié)構(gòu)類似windows
的文件夾結(jié)構(gòu),我們可以在任何時候在一個維度對這個集合進行擴展
,我們可以添加一個具體的節(jié)點
,也可以添加一個對象聚合
,如果這些添加的對象和聚合的接口全部是覆寫
自父類的接口,那我們就可以像文中那樣一視同仁的對待每一個節(jié)點,因為他們都繼承自一個父類,接口也是相同的.這個時候,我們可以很輕松的利用遞歸
來完成對這個樹
的遍歷,這是一種很巧妙地方式.
具體怎么做呢?我們可以在抽象類中寫出覆寫沒有用到所有的接口,在實現(xiàn)中讓他們?nèi)繏伋?code>異常,這在JAVA
中是一種很常見的做法,當(dāng)然,我們在OC
中這樣直接拋出異常的方法還是過于剛猛和直接,可以用其他一些委婉的做法.這里為什么要將父類全部覆寫上異常呢?原因比較簡單,繼承的子類并不是需要覆寫全部的接口的,那些不需要的接口,就直接使用父類的異常實現(xiàn)就好了,這樣表面上看起來葉節(jié)點和組合其實是一致的
.