這是我參與8月更文挑戰的第12天,活動詳情查看:8月更文挑戰java
繼Java設計模式-外觀模式後的組合模式它也來了哦,讓咱們一塊兒來瞧一瞧吧!!!😁 會了就當複習丫,不會來一塊兒來看看吧。web
很喜歡一句話:「八小時內謀生活,八小時外謀發展」。編程
若是你也喜歡,讓咱們一塊兒堅持吧!!
設計模式
共勉
😁安全
初入夏時
markdown
在現實生活中,存在不少「部分-總體」的關係,例如,大學中的部門與學院、總公司中的部門與分公司、學習用品中的書與書包、生活用品中的衣服與衣櫃、以及廚房中的鍋碗瓢盆等。ide
在軟件開發中也是如此,如,文件系統中的文件與文件夾、窗體程序中的簡單控件與容器控件等。對這些簡單對象與複合對象的處理,若是用組合模式來實現會很方便。post
組合模式(Composite Pattern):將對象組合成樹形結構以表示「部分總體」的層次結構。組合模式使得用戶對單個對象和組合對象的使用具備一致性。。學習
有時候又叫作部分-總體模式,它使咱們樹型結構的問題中,模糊了簡單元素和複雜元素的概念,客戶程序能夠像處理簡單元素同樣來處理複雜元素,從而使得客戶程序與複雜元素的內部結構解耦。測試
1.抽象根節點Component 是組合中的對象聲明接口,在適當的狀況下,實現全部類共有接口的默認行爲。聲明一個接口用於訪問和管理Component子部件。
2.樹枝節點Composite 定義有枝節點行爲,用來存儲子部件,在Component接口中實現與子部件有關操做,如增長(add)和刪除(remove)等。
3.葉子節點Leaf 在組合中表示葉子結點對象,葉子結點沒有子結點。
1.你想表示對象的部分-總體層次結構
2.你但願用戶忽略組合對象與單個對象的不一樣,用戶將統一地使用組合結構中的全部對象。
組合模式正是應樹形結構而生,因此組合模式的使用場景就大都是是出現樹形結構的地方。
好比:文件目錄顯示,多級目錄呈現等樹形結構數據的操做。
案例:
以下圖,咱們在訪問別的一些管理系統時,常常能夠看到相似的菜單。一個菜單能夠包含菜單項(菜單項是指再也不包含其餘內容的菜單條目),也能夠包含帶有其餘菜單項的菜單,所以使用組合模式描述菜單就很恰當,咱們的需求是針對一個菜單,打印出其包含的全部菜單以及菜單項的名稱。
要實現該案例,咱們先畫出類圖:
代碼:
不論是菜單仍是菜單項,都應該繼承自統一的接口,這裏姑且將這個統一的接口稱爲菜單組件。
//菜單組件 不論是菜單仍是菜單項,都應該繼承該類
public abstract class MenuComponent {
protected String name;
protected int level;
//添加菜單
public void add(MenuComponent menuComponent){
System.out.println("文件不能添加菜單");
throw new UnsupportedOperationException();
}
//移除菜單
public void remove(MenuComponent menuComponent){
System.out.println("文件不能移除菜單");
throw new UnsupportedOperationException();
}
//獲取指定的子菜單
public MenuComponent getChild(int i){
System.out.println("文件沒有子菜單");
throw new UnsupportedOperationException();
}
//獲取菜單名稱
public String getName(){
return name;
}
public void print(){
throw new UnsupportedOperationException();
}
}
複製代碼
這裏的MenuComponent定義爲抽象類,由於有一些共有的屬性和行爲要在該類中實現,Menu和MenuItem類就能夠只覆蓋本身感興趣的方法,而不用搭理不須要或者不感興趣的方法。
舉例來講,Menu類能夠包含子菜單,所以須要覆蓋add()、remove()、getChild()方法,可是MenuItem就不該該有這些方法。
我這裏就是打印句話,而後拋出異常。
Menu
Menu類已經實現了除了getName方法的其餘全部方法,由於Menu類具備添加菜單,移除菜單和獲取子菜單的功能。
public class Menu extends MenuComponent {
private List<MenuComponent> menuComponentList;
public Menu(String name,int level){
this.level = level;
this.name = name;
menuComponentList = new ArrayList<MenuComponent>();
}
@Override
public void add(MenuComponent menuComponent) {
menuComponentList.add(menuComponent);
}
@Override
public void remove(MenuComponent menuComponent) {
menuComponentList.remove(menuComponent);
}
@Override
public MenuComponent getChild(int i) {
return menuComponentList.get(i);
}
@Override
public void print() {
for (int i = 1; i < level; i++) {
System.out.print("--");
}
System.out.println(name);
for (MenuComponent menuComponent : menuComponentList) {
menuComponent.print();
}
}
}
複製代碼
MenuItem
MenuItem是菜單項,不能再有子菜單,因此添加菜單,移除菜單和獲取子菜單的功能並不能實現。
public class MenuItem extends MenuComponent {
public MenuItem(String name,int level) {
this.name = name;
this.level = level;
}
@Override
public void print() {
for (int i = 1; i < level; i++) {
System.out.print("--");
}
System.out.println(name);
}
}
複製代碼
測試
public class Client {
public static void main(String[] args) {
MenuComponent component = new Menu("crush",2);
MenuComponent c2 = new Menu("wyh1",1);
MenuComponent wyh4 = new MenuItem("wyh4", 2);
MenuComponent wyh5 = new MenuItem("wyh5", 2);
component.add(c2);
component.add(wyh4);
//wyh4.add(wyh5);
component.print();
/** * 輸出: * --crush * wyh1 * --wyh4 */
}
}
複製代碼
上面這個代碼案例,是屬於組合模式中的透明模式,你沒看錯,組合模式有兩種。我忘記寫在前面啦,這裏再來給你們介紹一下哈:
透明組合模式
透明組合模式中,抽象根節點角色中聲明瞭全部用於管理成員對象的方法,好比在示例中 MenuComponent
聲明瞭 add
、remove
、getChild
方法,這樣作的好處是確保全部的構件類都有相同的接口。透明組合模式也是組合模式的標準形式。
透明組合模式的缺點是不夠安全,由於葉子對象和容器對象在本質上是有區別的,葉子對象不可能有下一個層次的對象,即不可能包含成員對象,所以爲其提供 add()、remove() 等方法是沒有意義的,這在編譯階段不會出錯,但在運行階段若是調用這些方法可能會出錯(若是沒有提供相應的錯誤處理代碼)
安全組合模式
在安全組合模式中,在抽象構件角色中沒有聲明任何用於管理成員對象的方法,而是在樹枝節點 Menu
類中聲明並實現這些方法。安全組合模式的缺點是不夠透明,由於葉子構件和容器構件具備不一樣的方法,且容器構件中那些用於管理成員對象的方法沒有在抽象構件類中定義,所以客戶端不能徹底針對抽象編程,必須有區別地對待葉子構件和容器構件。
你卷我卷,你們卷,何時這條路纔是個頭啊。😇(仍是直接上天吧)
有時候也想停下來歇一歇,一直作一個事情,感受挺難堅持的。😁
你好,若是你正巧看到這篇文章,而且以爲對你有益的話,就給個贊吧,讓我感覺一下分享的喜悅吧,蟹蟹。🤗
如如有寫的有誤的地方,也請你們不嗇賜教!!
一樣如如有存在疑惑的地方,請留言或私信,定會在第一時間回覆你。
持續更新中