組合模式允許用戶將物件組合成樹形結構來表現“整體/部分”的層次結構,從而能夠以一致的方式處理單個物件以及物件組合,根據這個定義,首先能夠想到的就是軟體的選單,一個選單可以包含選單項(選單項是指不再包含其他內容的選單條目),也可以包含帶有其他選單項的選單,因此使用組合模式描述選單就很恰當,我們的需求是針對一個選單,列印出其包含的所有選單以及選單項,
首先,不管是選單還是選單項,都應該繼承自統一的介面,這里姑且將這個統一的介面稱為選單組件,其定義如下:

1 public abstract class MenuComponent { 2 public void add(MenuComponent menuComponent){ 3 throw new UnsupportedOperationException(); 4 } 5 6 public void remove(MenuComponent menuComponent){ 7 throw new UnsupportedOperationException(); 8 } 9 10 public MenuComponent getChild(int i){11 throw new UnsupportedOperationException();12 }13 14 public String getName(){15 throw new UnsupportedOperationException();16 }17 18 public String getDescription(){19 throw new UnsupportedOperationException();20 }21 22 public void print(){23 throw new UnsupportedOperationException();24 }25 }MenuComponent
這里選擇抽象類來實作MenuComponent,是因為需要對一些方法給出默認實作,如此一來,Menu和MenuItem類就可以只覆寫自己感興趣的方法,而不用搭理不需要或者不感興趣的方法,舉例來說,Menu類可以包含子選單,因此需要覆寫add()、remove()、getChild()方法,但是MenuItem就不應該有這些方法,這里給出的默認實作是拋出例外,你也可以根據自己的需要改寫默認實作,
接下來定義選單類Menu:

1 public class Menu extends MenuComponent{ 2 private List<MenuComponent> menuComponentList; 3 private String name; 4 private String descrition; 5 6 public Menu(String name, String description){ 7 this.name = name; 8 this.descrition = description; 9 menuComponentList = new ArrayList<>();10 }11 12 @Override13 public void add(MenuComponent menuComponent){14 menuComponentList.add(menuComponent);15 }16 17 @Override18 public void remove(MenuComponent menuComponent){19 menuComponentList.remove(menuComponent);20 }21 22 @Override23 public MenuComponent getChild(int i){24 return menuComponentList.get(i);25 }26 27 @Override28 public String getName() {29 return name;30 }31 32 @Override33 public String getDescription(){34 return descrition;35 }36 37 @Override38 public void print(){39 System.out.println(getName() + ", " + getDescription());40 Iterator iterator = menuComponentList.iterator();41 while(iterator.hasNext()){42 MenuComponent menuComponent = (MenuComponent) iterator.next();43 menuComponent.print();44 }45 }46 }Menu
Menu類應該覆寫自己感興趣的方法,實際上這里它覆寫了父類的所有方法,這樣做的原因僅僅是因為抽象類中的所有方法都是該類需要的,假設某一天我們在MenuComponent里面增加了color()方法,該方法只針對選單項顯示灰色底色,那么Menu累就不應該覆寫color()方法了,
讓我們接著來實作MenuItem:

1 public class MenuItem extends MenuComponent{ 2 private String name; 3 private String descrition; 4 5 public MenuItem(String name, String descrition){ 6 this.name = name; 7 this.descrition = descrition; 8 } 9 10 @Override11 public String getName() {12 return name;13 }14 15 @Override16 public String getDescription(){17 return descrition;18 }19 20 @Override21 public void print(){22 System.out.println(getName() + ", " + getDescription());23 }24 }MenuItem
MenuItem只覆寫了getName()、getDescription()、print()方法,因為其他的方法對該類并不適用,
現在可以寫個測驗類看一下組合模式在選單上面的表現了:
1 public class MenuComponentTest { 2 public static void main(String[] args){ 3 MenuComponentTest test = new MenuComponentTest(); 4 MenuComponent allMenu = test.createMenu(); 5 allMenu.print(); 6 } 7 8 public MenuComponent createMenu(){ 9 MenuComponent fileMenu = new Menu("檔案", "檔案相關選項");10 fileMenu.add(new MenuItem("設定", "可以更改一些設定項"));11 fileMenu.add(new MenuItem("保存", "保存所有檔案"));12 13 MenuComponent saveAsMenu = new Menu("另存為", "另存為其他一些格式");14 saveAsMenu.add(new MenuItem("PDF", "另存為PDF格式"));15 saveAsMenu.add(new MenuItem("docx","另存為docx格式"));16 fileMenu.add(saveAsMenu);17 18 MenuComponent helpMenu = new Menu("幫助","一些輔助項");19 helpMenu.add(new MenuItem("關于我們","軟體制作方的一些訊息"));20 helpMenu.add(new MenuItem("幫助中心","電話和郵箱咨詢"));21 22 MenuComponent allMenu = new Menu("所有選單","包含所有選單的選單");23 allMenu.add(fileMenu);24 allMenu.add(helpMenu);25 26 return allMenu;27 }28 }
列印結果為(沒有縮進所以稍微丑了一點):
所有選單, 包含所有選單的選單檔案, 檔案相關選項設定, 可以更改一些設定項保存, 保存所有檔案另存為, 另存為其他一些格式PDF, 另存為PDF格式docx, 另存為docx格式幫助, 一些輔助項關于我們, 軟體制作方的一些訊息幫助中心, 電話和郵箱咨詢最后回顧一下這個選單的例子,類之間的關系如下:

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/39951.html
標籤:設計模式
下一篇:通俗易懂設計模式決議——狀態模式

