标签:
组合模式允许将对象组合成树形结构来表示“整体与部分”的层次结构,能让给客户以一致的方式来处理个别对象以及对象组合。
以菜单为例思考,这个模式可以创建一个树形结构,在同一个结构中处理嵌套菜单和菜单项组,菜单包含子菜单,子菜单下分为菜单项,任何一个菜单都是一种组合,它既可以包含其他菜单,也可以包含菜单项。

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

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

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();
}
}
结果是

在组合模式中,客户并不需要知道具体有哪些类,只需要知道一个接口,不需要知道哪些是父对象哪些是子对象,也就不需要写大量的判断语句了。
标签:
原文地址:http://www.cnblogs.com/qingfei1994/p/4261682.html