現在我們已經能愉快地看著一頁一頁羅列出來的菜單進行點菜了。現在又有的小伙伴希望能夠加上一份餐後甜點的“子菜單”。怎麼辦呢?我們不僅僅要支持多個菜單,甚至還要支持菜單中的菜單。 如果我們能讓甜點菜單變成餐廳菜單集合的一個元素,那該有多好。但是根據現在的實現,根本做不到呀。我們想要的是這樣的: 我們需要 ...
現在我們已經能愉快地看著一頁一頁羅列出來的菜單進行點菜了。現在又有的小伙伴希望能夠加上一份餐後甜點的“子菜單”。怎麼辦呢?我們不僅僅要支持多個菜單,甚至還要支持菜單中的菜單。
如果我們能讓甜點菜單變成餐廳菜單集合的一個元素,那該有多好。但是根據現在的實現,根本做不到呀。我們想要的是這樣的:
我們需要什麼
現在我們遇到的現實問題是,我們的系統已經達到了一個複雜的級別,如果現在不重新設計,就無法容納未來增加的菜單或子菜單等需求。
所以,在我們的新設計中,真正需要些什麼呢?
- 我們需要某種樹形結構,可以容納菜單、子菜單和菜單項
- 我們需要確定能夠在每個菜單的各個項之間游走,而且至少要像現在用迭代器一樣方便
- 我們也需要能夠更有彈性地在菜單項之間游走。比方說,可能只需要遍歷甜點菜單,或者可以遍歷餐廳的整個菜單(包括甜點菜單在內)。
定義組合模式
沒錯,我們要介紹另一個模式解決這個難題。我們並沒有放棄迭代器--它仍然是我們解決方案中的一部分--然而,管理菜單的問題已經到了一個迭代器無法解決的新維度。所以,我們將倒退幾步,改用組合模式來實現。
組合模式:允許你將對象組合成樹形結構來表現“整體/部分”層次結構。組合能讓客戶以一致的方式處理個別對象以及對象組合。
讓我們以菜單為例思考這一切:這個模式能夠創建一個樹形結構,在同一個結構中處理嵌套菜單和菜單項組。通過將菜單和項放在相同的結構中,我們創建了一個“整體/部分”層次結構,即由菜單和菜單項組成的對象樹。但是可以將它視為一個整體,像是一個豐富的大菜單。
一旦有了豐富的大彩蛋,我們就可以使用這個模式來“統一處理個別對象和組合對象”。這意味著什麼?它意味著,如果我們有了一個樹形結構的菜單、子菜單和可能還帶有菜單項的子菜單,那麼任何一個菜單都是一種“組合”。
因為它既可以包含其他菜單,也可以包含菜單項。個別對象只是菜單項--並未持有其他對象。就像你將看到,使用一個遵照組合模式的設計,讓我們能夠寫出簡單的代碼,就能夠對整個菜單結構應用相同的操作。
結合圖來描述如下:
組合模式的類圖如下:
瞭解完組合模式的種種,在下次的推文中,我們將用於實際操作。我們利用組合模式設計菜單,並且使用菜單,以此來鞏固加深。敬請期待吧。