java_composite

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



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值