java_composite
来源:互联网 发布:传媒大数据 编辑:程序博客网 时间:2024/06/05 10:40
introduction:
组合模式:
允许你将对象组合成树形结构来表现“整体/部分”层次结构。组合能让客户以一致的方式处理个别对象以及对象组合。
组合模式让我们能用树形方式创建对象的结构,树里面包含了组合及个别的对象。
使用组合结构,我们能把相同的操作运用在组合和个别对象上。换句话说,在大多数情况下,我们可以忽略对象组合和个别对象之间的差别。
为了保证透明性,组合内所有的对象都必须实现相同的接口,这意味着对象具备一些没有意义的方法调用。
对于没哟意义的方法我们可以返回null或false,甚至可以抛出一个异常
demo: 以迭代器模式一样,模拟一天三餐,现在的情况与迭代器不同的是:我们现在可以组合菜单,顾名思义,我们现在一个菜单项可以出现在不同的菜单中,同样,一个菜单也可能出现在另一个菜单中,总而言之,现在的菜单结构变成了一个树形结构。树形结构的叶子节点相当于一个个菜单项,每一个中间节点相当于一个菜单。
description:
在组合模式中,所有的对象都继承于一个公共接口,公共接口中提供所有整体和部分分别需要实现的方法。
Component.java
public abstract class Component { public void add(Component component){ throw new UnsupportedOperationException(); } public void remove(Component component){ throw new UnsupportedOperationException(); } public void print(){ throw new UnsupportedOperationException(); } public void getName(String name){ throw new UnsupportedOperationException(); } public void getPrice(Double price){ throw new UnsupportedOperationException(); } public Component getChild(int i){ throw new UnsupportedOperationException(); } public Iterator<Component> createIterator(){ throw new UnsupportedOperationException(); }}对于叶子节点只需要实现公共接口中有用的方法
Leaf.java
/** * 该类为一个个别对象,也就是组合模式中所说的部分 * 该类只需要重写公共接口中的一部分方法(因为有些方法在这个类中不适用) */public class Leaf extends Component{ private String name; private Double price; /** * @param name * @param price */ public Leaf(String name, Double price) { this.name = name; this.price = price; } @Override public void getName(String name) { this.name = name; } @Override public void getPrice(Double price) { this.price = price; } @Override public void print() { System.out.println("--- leaf ---"); System.out.print(name+"---"); System.out.println(price); } @Override public Iterator<Component> createIterator() { return new NullIterator(); } }
空迭代器:实际上什么也没有做,可是这样做不会返回null
NullIterator.java
public class NullIterator implements Iterator<Component>{ @Override public boolean hasNext() { return false; } @Override public Component next() { return null; } @Override public void remove() { throw new UnsupportedOperationException(); }}
对于组合节点同样只需要实现公共接口中有用的接口就可以了
Composite.java/** * 该类为一个组合对象,也就是我们所说的整体 * 同样该类只需要重写公共接口中一部分方法 */public class Composite extends Component{ private ArrayList<Component> components = new ArrayList<Component>(); private String name; private Double price; /** * @param name * @param price */ public Composite(String name, Double price) { this.name = name; this.price = price; } @Override public void add(Component component) { components.add(component); } @Override public void remove(Component component) { components.remove(component); } @Override public void print() { System.out.println("--- Composite ---"); System.out.print(name+" --- "); System.out.println(price+" --- "); Iterator<Component> componentIterator = components.iterator(); while(componentIterator.hasNext()){ componentIterator.next().print(); } } @Override public Iterator<Component> createIterator() { return new CompositeIterator(components.iterator()); } }下面这段代码是难点,下面实现的是一个外部迭代器,所以必须维护它在遍历中的位置,以便外部客户可以通过hasNext()和next()来驱动遍历。
CompositeIterator.java
public class CompositeIterator implements Iterator<Component>{ /** * 将所有的迭代器都存储在栈中 */ private Stack<Iterator<Component>> stack = new Stack<Iterator<Component>>(); public CompositeIterator(Iterator<Component> componentIterator){ stack.push(componentIterator); } /** * */ @Override public boolean hasNext() { if(stack.isEmpty()){ return false; }else{ Iterator<Component> iterator = stack.peek(); if(!iterator.hasNext()){ stack.pop(); return hasNext(); }else{ return true; } } } @Override public Component next() { if(hasNext()){ Iterator<Component> iterator = stack.peek(); Component component = iterator.next(); if(component instanceof Composite){ stack.push(component.createIterator()); } return component; } return null; } @Override public void remove() { throw new UnsupportedOperationException(); }}
最后,测试以上代码:
Test.java
public class Test { public static void main(String[] args) { Component breakfast = new Composite("早餐",5.00); Component lunch = new Composite("午餐",15.00); Component diner = new Composite("晚餐",10.00); Component drink = new Composite("饮料",3.00); breakfast.add(new Leaf("面包",2.00)); breakfast.add(new Leaf("牛奶",3.00)); lunch.add(new Leaf("带鱼",5.00)); lunch.add(new Leaf("臭豆腐",3.00)); lunch.add(new Leaf("茄子烧肉",4.00)); lunch.add(drink); diner.add(new Leaf("红烧鳊鱼",5.00)); diner.add(new Leaf("鸡蛋菜汤",3.00)); diner.add(new Leaf("青菜",2.00)); diner.add(lunch); drink.add(new Leaf("冰红茶",3.00)); Component components = new Composite("一天三餐",30.00); components.add(breakfast); components.add(lunch); components.add(diner); Client c = new Client(components); c.printComponent(); }}
输出结果:
--- Composite ---
一天三餐 --- 30.0 ---
--- Composite ---
早餐 --- 5.0 ---
--- leaf ---
面包---2.0
--- leaf ---
牛奶---3.0
--- Composite ---
午餐 --- 15.0 ---
--- leaf ---
带鱼---5.0
--- leaf ---
臭豆腐---3.0
--- leaf ---
茄子烧肉---4.0
--- Composite ---
饮料 --- 3.0 ---
--- leaf ---
冰红茶---3.0
--- Composite ---
晚餐 --- 10.0 ---
--- leaf ---
红烧鳊鱼---5.0
--- leaf ---
鸡蛋菜汤---3.0
--- leaf ---
青菜---2.0
--- Composite ---
午餐 --- 15.0 ---
--- leaf ---
带鱼---5.0
--- leaf ---
臭豆腐---3.0
--- leaf ---
茄子烧肉---4.0
--- Composite ---
饮料 --- 3.0 ---
--- leaf ---
冰红茶---3.0