package composite; import java.util.ArrayList; import java.util.Iterator; /** * @author jiq * 类型:Structural * 定义: 组合模式(Composite)允许你讲对象组合成属性结构来表现“整体/部分”的层次结构。 * 组合能让客户以一致的方式对待这个层次结构中的个别对象以及对象组合。 * * 用途: 这个模式能够创建一个树形结构,在同一个结构中处理嵌套菜单和菜单项。通过将 * 菜单和菜单项放在相同的结构中,我们创建了一个“整体/部分”层次结构。我们将其 * 视为一个丰富的大菜单,一旦有了这个大菜单,我们就可以使用这个模式来“统一处理 * 个别对象和组合对象”。这意味着我们可以对整个菜单结构应用相同的操作,比如打印。 * --- 当你有一个对象的集合,他们彼此之间有“整体/部分”的关系,并且你想用一致的 * 方法对待这些对象的时候,你就需要组合模式。 * --- “整体/部分”关系指的是,举个例子,用户界面,经常会看到一个顶层组件(Frame * 或Panel)包含其他组件(菜单,文字,按钮等),所有这些单独看来都是部分,他们 * 所有加起来就是整体。 * --- “一致的方法对待这些对象”是指“组合对象”和“叶节点”对象具有共同的方法可以调用。 * 但是他们各自回做出正确的事情,组合对象会叫他的所有组件(组合对象或者叶节点)显示。 * * 最大优势:客户不需要在操心自己面对的是组合对象还是叶节点对象,客户只需要对整个结构调用 * 一个方法并执行操作就可以了。 * 应用: 文件系统中的File对象,既可以是目录(组合对象,包含目录或者文件),也可以是文件(叶节点)。 * */ //抽象菜单组件,所有方法不是必须实现,所以没有声明为abstract 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(); } } //菜单(组合对象) class Menu extends MenuComponent { //菜单包含其它的(菜单/菜单项)作为子节点,即组合对象中包含其他组件(组合对象/叶节点) ArrayList<MenuComponent> menuComponents = new ArrayList<MenuComponent>(); String name; public Menu(String name) { this.name = name; } public void add(MenuComponent menuComponent) { menuComponents.add(menuComponent); } public void remove(MenuComponent menuComponent) { menuComponents.remove(menuComponent); } public MenuComponent getChild(int i) { return (MenuComponent)menuComponents.get(i); } public String getName() { return name; } public void print() { System.out.print("\n" + getName()); System.out.println("---------------------"); //使用迭代器模式遍历所有子节点 Iterator<MenuComponent> iterator = menuComponents.iterator(); while (iterator.hasNext()) { MenuComponent menuComponent = (MenuComponent)iterator.next(); menuComponent.print(); } } } //菜单项(叶节点对象) class MenuItem extends MenuComponent { String name; double price; public MenuItem(String name,double price) { this.name = name; this.price = price; } public String getName() { return name; } public double getPrice() { return price; } public void print() { System.out.print(" " + getName()); System.out.println(", " + getPrice()); } } //测试组合模式 public class Composite { public static void main(String[] args) { MenuComponent pancakeHouseMenu = new Menu("PANCAKE HOUSE MENU"); MenuComponent dinerMenu = new Menu("DINER MENU"); MenuComponent cafeMenu = new Menu("CAFE MENU"); MenuComponent coffeeMenu = new Menu("COFFEE MENU"); //大菜单的根节点 MenuComponent allMenus = new Menu("ALL MENUS"); //添加节点 allMenus.add(pancakeHouseMenu); allMenus.add(dinerMenu); allMenus.add(cafeMenu); pancakeHouseMenu.add(new MenuItem("K&B's Pancake Breakfast",2.99)); pancakeHouseMenu.add(new MenuItem("Regular P Breakfast",2.22)); dinerMenu.add(new MenuItem("Vegetarian BLT",3.99)); dinerMenu.add(new MenuItem("BLT",2.99)); cafeMenu.add(new MenuItem("Burrito",4.29)); cafeMenu.add(coffeeMenu); coffeeMenu.add(new MenuItem("Coffee Cake",1.59)); allMenus.print(); //打印整个大菜单 } }