组合模式允许你将对象组合成树形结构来表现“整体部分”层次结构,组合能让用户以一致的方式来处理个别对象和组合对象。
以菜单为例,因为子菜单的存在,所以当遍历菜单时,会遇到个别对象(菜单项)和对象组合(子菜单)。
还好有组合模式。。。
现在创建一个组件接口来作为菜单和菜单项的共同接口,让我们能够用统一的做法来处理菜单和菜单项。换句话说,我们可以针对菜单和菜单项调用相同的方法。。。But,菜单组件好像扮演了两个角色,是的,确实扮演了两个角色,Y?
组合模式以单一责任设计原则换取透明性。通过让组件的接口同时包含一些管理子节点和叶节点的操作,客户就可以将组合和叶节点一视同仁。也就是说,一个元素究竟是叶节点还是组合,对客户是透明的。
因为最好能够为这些方法提供默认的实现,so。。。抽象类的干活。。。
代码示例:
public abstract class MenuComponent { public void Add (MenuComponent menuComponent) { throw new Exception(); } public void Remove(MenuComponent menuComponent) { throw new Exception(); } public string getName() { throw new Exception(); } public boolean IsVeg () { throw new Exception(); } public void print() { throw new Exception(); } }
因为有些方法只对菜单项有意义,另一些方法只对菜单有意义,默认实现是抛出异常,这样,若菜单(项)不支持某个方法,直接继承默认实现就OK了。
下面实现菜单项的类,该类只要实现对它有意义的方法即可:
public class MenuItem extends MenuComponent { string name; boolean veg; public MenuItem(string name, boolean veg) { this.name = name; this.veg = veg; } public string getName() { return name; } public boolean IsVeg() { return veg; } public void print() { system.out.print("this is " + getName()); } }
下面实现菜单的类,同样,该类只要实现对它有意义的方法即可:
public class Menu extends MenuComponent { string name; ArrayList menuComponents = new ArrayList(); public Menu(string name) { this.name = name; } public string getName() { return name; } public void Add(MenuComponent menuComponent) { menuComponents.add(menuComponent); } public void Remove(MenuComponent menuComponent) { menuComponents.remove(menuComponent); } public void print() { system.out.print("this is " + getName() + "菜单,包含:"); // 该部分采用了迭代器模式 Iterator iterator = menuComponents.iterator(); while(iterator.hasNext()) { MenuComponent menuComponent = (MenuComponent) iterator.next(); menuComponent.print() // 递归 } } }
。。。。。。
这样我们可以使用menuComponent来处理菜单和菜单项了,而不必去理会该对象是菜单项(个别对象)还是菜单(组合对象)。。。