组合模式:组合模式允许你将对象组合成树形结构来表现“整体/部分”层次结构。组合能让客户以一致的方式处理个别对象以及对象组合。
组合模式让我们能用树形方式创建对象的结构,树里面包含了组合以及个别的对象。
使用组合的结构,我们能把相同的操作应用在组合和个别对象上。换句话说,在大多数情况下,我们可以忽略对象组合和个别对象之间的差异。
菜单与菜单项:现在有一个菜单,包含了3个菜单项 ,包含了2个子菜单。
2个子菜单中,1号子菜单有2个菜单项,2号子菜单有1个菜单项
菜单 相当于对象组合,菜单项相当于个别对象。
结构图:
类图:
菜单节点 MenuComponent类
1 /** 2 * 这是 菜单节点的 父类MenuComponent 3 * 我们将菜单项MenuItem和菜单Menu 都看做是菜单节点MenuComponent 4 * 但是菜单项MenuItem 从菜单节点MenuComponent 中继承下来的某些方法对它是无意义的 如add,remove 5 * 但是菜单Menu 从菜单节点MenuComponent 中继承下来的某些方法对它是无意义的 如getPrice,isVegetable 6 * @author wly 7 * 8 */ 9 public class MenuComponent { 10 /** 11 * 为这个菜单节点 增加一个菜单项或者菜单 菜单可以用 菜单项不能用 12 * @param menu 13 */ 14 public void add(MenuComponent menuComponent) 15 { 16 throw new UnsupportedOperationException("当前组件不支持该方法!"); 17 } 18 /** 19 * 为这个菜单节点 删除一个菜单项或者菜单 菜单可以用 菜单项不能用 20 * @param menu 21 */ 22 public void remove(MenuComponent menuComponent) 23 { 24 throw new UnsupportedOperationException("当前组件不支持该方法!"); 25 } 26 /** 27 * 返回这个菜单节点的名称 菜单和菜单项均可以使用 28 * @return 29 */ 30 public String getName() 31 { 32 throw new UnsupportedOperationException("当前组件不支持该方法!"); 33 } 34 /** 35 * 返回这个菜单节点的描述信息 菜单和菜单项均可以使用 36 * @return 37 */ 38 public String getDescription() 39 { 40 throw new UnsupportedOperationException("当前组件不支持该方法!"); 41 } 42 /** 43 * 返回这个菜单节点的价格 菜单不可用 菜单项可以使用 44 * @return 45 */ 46 public Double getPrice() 47 { 48 throw new UnsupportedOperationException("当前组件不支持该方法!"); 49 } 50 /** 51 * 返回这个菜单节点的是否是素食 菜单不可用 菜单项可以使用 52 * @return 53 */ 54 public Boolean isVegetable() 55 { 56 throw new UnsupportedOperationException("当前组件不支持该方法!"); 57 } 58 /** 59 * 打印这个菜单节点的 信息 菜单和菜单项均可以使用 60 * @return 61 */ 62 public void print() 63 { 64 throw new UnsupportedOperationException("当前组件不支持该方法!"); 65 } 66 }
菜单项 MenuItem类
1 /** 2 * 这是 菜单项的类 MenuItem 它继承MenuComponent类 3 * 由于MenuComponent类 默认对所有的方法都抛出不可用的异常 所以菜单项需要将 它可以使用的方法进行重写 4 * @author wly 5 * 6 */ 7 public class MenuItem extends MenuComponent { 8 private String name; 9 private String description; 10 private double price; 11 private Boolean isVegetable; 12 13 public MenuItem(String name, String description, double price, 14 Boolean isVegetable) { 15 super(); 16 this.name = name; 17 this.description = description; 18 this.price = price; 19 this.isVegetable = isVegetable; 20 } 21 22 @Override 23 public String getName() 24 { 25 return this.name; 26 } 27 @Override 28 public String getDescription() 29 { 30 return this.description; 31 } 32 @Override 33 public Double getPrice() 34 { 35 return this.price; 36 } 37 @Override 38 public Boolean isVegetable() 39 { 40 return this.isVegetable; 41 } 42 @Override 43 public void print() 44 { 45 System.out.println("名称:"+getName()); 46 System.out.println("描述:"+getDescription()); 47 System.out.println("是否是素食:"+isVegetable()); 48 System.out.println("价格:"+getPrice()); 49 System.out.println("********************"); 50 } 51 }
菜单类 Menu类
1 /** 2 * 这是 菜单的类 Menu 它继承MenuComponent类 3 * 由于MenuComponent类 默认对所有的方法都抛出不可用的异常 所以菜单需要将 它可以使用的方法进行重写 4 * @author wly 5 * 6 */ 7 public class Menu extends MenuComponent { 8 //一个菜单 可以包含若干个菜单项 和 子菜单 采用一个集合来保存 9 private List<MenuComponent> menuList; 10 private String name; 11 private String description; 12 public Menu(String name, String description) { 13 super(); 14 this.name = name; 15 this.description = description; 16 this.menuList = new ArrayList<MenuComponent>(); 17 } 18 @Override 19 public void add(MenuComponent menuComponent) 20 { 21 menuList.add(menuComponent); 22 } 23 @Override 24 public void remove(MenuComponent menuComponent) 25 { 26 menuList.remove(menuComponent); 27 } 28 @Override 29 public String getName() 30 { 31 return this.name; 32 } 33 @Override 34 public String getDescription() 35 { 36 return this.description; 37 } 38 @Override 39 public void print() 40 { 41 System.out.println("名称:"+getName()); 42 System.out.println("描述:"+getDescription()); 43 System.out.println("****************"); 44 Iterator<MenuComponent> iterator = menuList.iterator(); 45 while(iterator.hasNext()) 46 { 47 MenuComponent m = iterator.next(); 48 m.print(); //在打印时,如果m是菜单项 就会调用菜单项MenuItem的print方法 49 //若果是子菜单 就会调用Menu的 print方法,形成递归调用。 50 } 51 } 52 }
最后提供一个测试类:
1 public class TestClass { 2 3 /** 4 * @param args 5 */ 6 public static void main(String[] args) { 7 MenuComponent mainMenu = new Menu("主菜单", "主菜单:包含三个菜单项,两个子菜单"); 8 MenuComponent menuItem1 = new MenuItem("AA", "这是菜单项AA", 1.99, true); 9 MenuComponent menuItem2 = new MenuItem("BB", "这是菜单项BB", 2.99, false); 10 MenuComponent menuItem3 = new MenuItem("CC", "这是菜单项CC", 3.99, true); 11 12 mainMenu.add(menuItem1); 13 mainMenu.add(menuItem2); 14 mainMenu.add(menuItem3); 15 16 MenuComponent menu1 = new Menu("子菜单1","子菜单1:包含两个菜单项"); 17 MenuComponent menuItem4 = new MenuItem("DD", "这是菜单项DD", 4.99, false); 18 MenuComponent menuItem5 = new MenuItem("EE", "这是菜单项EE", 5.99, true); 19 menu1.add(menuItem4); 20 menu1.add(menuItem5); 21 22 MenuComponent menu2 = new Menu("子菜单2","子菜单2:包含一个菜单项"); 23 MenuComponent menuItem6 = new MenuItem("FF", "这是菜单项FF", 6.99, false); 24 menu2.add(menuItem6); 25 26 mainMenu.add(menu1); 27 mainMenu.add(menu2); 28 29 mainMenu.print(); 30 31 } 32 33 }
输出的结果如下: