Java 设计模式之组合模式
一、了解組合模式
1.1 什么是組合模式
組合模式允許你將對象組合成樹形結構來表現“整體/部分”層次機構。組合能夠使客戶以一致的方式處理個別對象以及組合對象。
組合模式讓我們能夠用樹形方式創建對象的結構,樹里面包含了組合以及個別的對象。
使用組合結構,我們能夠把相同的操作應用在組合和個別對象上。換句話說,在大多數情況下,我們可以忽略對象組合和個別對象之間的差別。
1.2 組合模式組成結構
- Component :是組合中的對象聲明接口,在適當的情況下,實現所有類共有接口的默認行為。聲明一個接口用于訪問和管理 Component 子部件。
- Leaf :在組合中表示葉子結點對象,葉子結點沒有子結點。
- Composite :定義有枝節點行為,用來存儲子部件,在 Component 接口中實現與子部件有關操作,如增加 (add) 和刪除 (remove) 等。
1.3 組合模式 UML 圖解
組合包含組件。組件有兩種:組合和葉節點元素。組合持有一群孩子,這些孩子可以分別是別的組合或者葉節點元素。當你使用這種方式組織數據的時候,最終會得到樹形結構 (由上而下的樹形結構),根部是一個組合,而組合的分支逐漸向下延伸,直到葉節點為止。
1.4 組合模式應用場景
- 想表示對象的部分-整體層次結構(樹形結構)。
- 希望用戶忽略組合對象與單個對象的不同,用戶將統一地使用組合結構中的所有對象。
二、組合模式具體應用
2.1 問題描述
打印菜單:通過代碼實現打印早、中、晚餐的菜單,列出所有的菜品,并且在晚餐菜單中包含甜品菜單。
2.2 問題樹形結構分析圖
2.3 使用組合模式設計相關類圖
2.4 代碼實現
MenuComponent 抽象類
package com.jas.component;/*** @author Jas* @create 2018-01-30 10:23**/ public abstract class MenuComponent {public void add(MenuComponent menuComponent){throw new UnsupportedOperationException();}public void remove(MenuComponent menuComponent){throw new UnsupportedOperationException();}public MenuComponent getChild(int i){throw new UnsupportedOperationException();}public String getName(){throw new UnsupportedOperationException();}public double getPrice(){throw new UnsupportedOperationException();}public void print(){throw new UnsupportedOperationException();}}組件 MenuItem 類
package com.jas.component;/*** 菜單項類實現,用來封裝菜品信息* * getName() 方法返回菜品名字* getPrice() 方法返回菜品價格* print() 輸出該菜品的詳細信息* * @author Jas* @create 2018-01-30 10:26**/ public class MenuItem extends MenuComponent{String name;double price;public MenuItem(String name, double price){this.name = name;this.price = price;}@Overridepublic String getName() {return name;}@Overridepublic double getPrice() {return price;}@Overridepublic void print() {System.out.print(" " + getName());System.out.println(" " + getPrice());} }組件 Menu 類
package com.jas.component;import java.util.ArrayList; import java.util.Iterator; import java.util.List;/*** 菜單類,* * getName() 方法返回具體菜單名* add(MenuComponent menuComponent) 方法表示添加菜單* remove(MenuComponent menuComponent) 刪除一個菜單* getChild(int i) 返回一個指定的菜單* print() 用于輸出菜單名和具體菜單菜品信息,也是所有代碼中最難理解的一部分* * @author Jas* @create 2018-01-30 10:30**/ public class Menu extends MenuComponent {/** menuComponents 用來保存早中晚的菜單項。 */List<MenuComponent> menuComponents = new ArrayList<>();/** name 表示菜單名 (早中晚甜品)*/String name;public Menu(String name){this.name = name;}@Overridepublic void add(MenuComponent menuComponent) {menuComponents.add(menuComponent);}@Overridepublic void remove(MenuComponent menuComponent) {menuComponents.remove(menuComponent);}@Overridepublic MenuComponent getChild(int i) {return menuComponents.get(i);}@Overridepublic String getName() {return name;}/*** 既可以輸出菜單名,也可以輸出菜單中的菜品名*/@Overridepublic void print() {System.out.println("\n" + getName());System.out.println("====================");Iterator<MenuComponent> iterator = menuComponents.iterator();while (iterator.hasNext()){MenuComponent menuComponent = iterator.next();menuComponent.print();}} }Waitress 類
package com.jas.component;/*** 招待員類* * @author Jas* @create 2018-01-30 10:39**/ public class Waitress {MenuComponent allMenus;public Waitress(MenuComponent allMenus){this.allMenus = allMenus;}public void print(){allMenus.print();} }測試類
package com.jas.component;/***測試類* * @author Jas* @create 2018-01-30 10:40**/ public class MenuTestDrive {public static void main(String[] args) {MenuComponent breakfastMenu = new Menu("早餐菜單");MenuComponent lunchMenu = new Menu("午餐菜單");MenuComponent dinnerMenu = new Menu("晚餐菜單");MenuComponent dessertMenu = new Menu("甜品菜單");/** 頂層菜單*/MenuComponent allMenus = new Menu("ALL MENUS LIST");breakfastMenu.add(new MenuItem("包子", 1.0));breakfastMenu.add(new MenuItem("豆漿",2.0));lunchMenu.add(new MenuItem("西紅柿蓋澆飯", 10.0));lunchMenu.add(new MenuItem("西紅柿雞蛋面",10.0));dinnerMenu.add(new MenuItem("熱狗", 15.0));dessertMenu.add(new MenuItem("蘋果派", 5.0));allMenus.add(breakfastMenu);allMenus.add(lunchMenu);allMenus.add(dinnerMenu);/** 將甜品菜單添加在晚餐菜單中*/dinnerMenu.add(dessertMenu);Waitress waitress = new Waitress(allMenus);waitress.print();} }/*** 輸出* ALL MENUS LIST* ====================** 早餐菜單* ====================* 包子 1.0* 豆漿 2.0** 午餐菜單* ====================* 西紅柿蓋澆飯 10.0* 西紅柿雞蛋面 10.0** 晚餐菜單* ====================* 熱狗 15.0** 甜品菜單* ====================* 蘋果派 5.0* */三、組合模式總結
3.1 組合模式優缺點
優點
- 高層模塊調用簡單。
- 節點可自由增加。
缺點
在使用組合模式時,其葉子和樹枝的聲明都是實現類,而不是接口,違反了面對抽象編程和依賴倒置原則。
3.2 組合模式知識點總結
- 組合模式提供一個結構,可同時包容個別對象和組合對象。
- 組合模式允許客戶對個別對象以及組合對象一視同仁。
- 組合結構內的任意對象稱為組件,組件可以是組合,也可以是葉節點。
- 在使用組合模式時,要多加考慮方式,有的時候可以與迭代器模式配合使用。
PS:點擊了解更多設計模式 http://blog.csdn.net/codejas/article/details/79236013
參考文獻
《Head First 設計模式》
總結
以上是生活随笔為你收集整理的Java 设计模式之组合模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 厨房打印机一菜一单怎么设置?
- 下一篇: 卧室床对着门好吗?