设计模式之组合模式

  组合模式允许将对象组合成树形结构来表示“整体与部分”的层次结构,能让给客户以一致的方式来处理个别对象以及对象组合。

  以菜单为例思考,这个模式可以创建一个树形结构,在同一个结构中处理嵌套菜单和菜单项组,菜单包含子菜单,子菜单下分为菜单项,任何一个菜单都是一种组合,它既可以包含其他菜单,也可以包含菜单项。

 

  菜单类和菜单项类继承同一个父类,继承的方法不同,但是我们可以忽略个别对象和对象组合的区别。

  组合模式的类图如下:

 

 下面我们结合迭代器模式和组合模式,实现遍历打印菜单,具体类图如下:

   

 MenuComponent类

 

import java.util.Iterator;
/**
   菜单组件类,菜单项和菜单都要继承的父类。
**/
public 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 String getPrice()
    {
        throw new UnsupportedOperationException();
    }
    public void print()
    {
        throw new UnsupportedOperationException();
    }
    public Iterator createIterator()
    {
        throw new UnsupportedOperationException();
    }
    
}
  

  

继承了MenuComponent类的Menu类

 

/**
菜单组件类,菜单项和菜单都要继承的父类。
**/
public class Menu extends MenuComponent
{
    ArrayList<MenuComponent> menuComponents;
    String name;
    public Menu(String name)
    {
        this.name=name;
        menuComponents=new ArrayList<MenuComponent>();
    }
    public void add(MenuComponent menuComponent)
    {
        menuComponents.add(menuComponent); 
    } 
    public void remove(MenuComponent menuComponent)
    {
        menuComponents.remove(menuComponent);
    }
    public MenuComponent getChild(int i)
    {
        return menuComponents.get(i);
    }
    public String getName()
    {
        return name;
    }
    public void print()
    {
        System.out.println("Menu:"+name);
        System.out.println("-----------------");
        Iterator iterator=createIterator();
        while(iterator.hasNext())
        {
            MenuComponent menuComponent=(MenuComponent)iterator.next();
            menuComponent.print();

        }
    }
    public Iterator createIterator()
    {
        return new CompositeIterator(menuComponents.iterator());
    }

}                                        

  

 继承了MenuComponent类的MenuItem类,相当于菜单项

 

import java.util.Iterator;
/**
   菜单项类,继承了菜单组件类
**/
public  class MenuItem extends MenuComponent
{
	String name;
	String price;
	public MenuItem(String name,String price)
	{
		this.name=name;
		this.price=price;	
	}
	
	public String getName()
	{
		return name;
	}
	public String getPrice()
	{
		return price;
	}
	public void print()
	{
		System.out.println(name+":"+price);
	}
	public Iterator createIterator()
	{
		return new NullIterator();
	}
	
}

  CompositeIterator类,作为菜单的迭代器

import java.util.*;
public class CompositeIterator implements Iterator
{
    Stack stack;
    public CompositeIterator(Iterator iterator)
    {
        stack=new Stack();
        stack.push(iterator);
    } 
    public Object next()
    {
        if(hasNext())
        {
            Iterator iterator=(Iterator)stack.peek();
            MenuComponent menuComponent=(MenuComponent)

iterator.next();
            if(menuComponent instanceof Menu)
            {
                stack.push(menuComponent.createIterator());
                
            }
            return menuComponent;
        }
        else
            return null;
    }
    public boolean hasNext()
    {
        if(stack.isEmpty())
        {
            return false;
        }
        else
        {
            Iterator iterator=(Iterator)stack.peek();
            if(!iterator.hasNext())
            {
                stack.pop();
                return hasNext();    
            }
            else
            {
                return true;
            }

        }
    }
    public void remove()
    {
        throw new UnsupportedOperationException();
    }




} 

 NullIterator类,作为菜单项的迭代器

import java.util.Iterator;
public class NullIterator implements Iterator
{
	public Object next()
	{
		return null;
	}
	public boolean hasNext()
	{
		return false;
	}
	public void remove()
	{
		throw new UnsupportedOperationException();
	}




}

   Waitress类,大大降低了Waitress类与菜单之间的耦合度,Waitress类只需要知道根节点就可以了。

  

import java.util.Iterator;
/**
Client
**/
public class Waitress
{
    MenuComponent menus;
    public Waitress(MenuComponent menuComponent)
    {
        this.menus=menuComponent;
    }
    public void printMenu()
    {
        menus.print();
    
    }
}

  

   测试类

   

package com.qingfei.composite;
public class Test
{
	public static void main(String[] args)
	{
		MenuComponent menus=new Menu("all Menu");
		MenuComponent dinerMenu=new Menu("Diner Menu");
		MenuComponent pancakeMenu=new Menu("Pancake Menu");
		MenuComponent cafeMenu=new Menu("cafe Menu");
		menus.add(dinerMenu);
		menus.add(pancakeMenu);
		dinerMenu.add(new MenuItem("noodle","10"));
		dinerMenu.add(new MenuItem("rice","20"));
		dinerMenu.add(new MenuItem("soup","5"));
		cafeMenu.add(new MenuItem("latte","30"));
		cafeMenu.add(new MenuItem("mocha","25"));	
		pancakeMenu.add(new MenuItem("pizza","50"));
		pancakeMenu.add(new MenuItem("cheese burger","20"));
		pancakeMenu.add(cafeMenu);
		Waitress service=new Waitress(menus);
		service.printMenu();

	}


}

    结果是

    

  在组合模式中,客户并不需要知道具体有哪些类,只需要知道一个接口,不需要知道哪些是父对象哪些是子对象,也就不需要写大量的判断语句了。

posted on 2015-01-30 13:45  qingfei  阅读(159)  评论(0编辑  收藏  举报