设计模式学习--迭代器模式(Iterator Pattern)和组合模式(Composite Pattern)

设计模式学习--迭代器模式(Iterator Pattern)

概述

———————————————————————————————————————————————————

迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示

把游走的任务放在迭代器上,而不是聚合上。这样简化了聚合的接口和实现,也让责任各得其所。


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

OO原则

———————————————————————————————————————————————————

  • 封装变化
  • 多用组合,少用继承
  • 针对接口编程,不针对实现编程
  • 为交互对象之间的松耦合设计而努力
  • 类应该对扩展开放,对修改关闭
  • 依赖抽象,不要依赖具体类
  • 只和朋友交谈
  • 别找我,我会找你
  • 类应该只有一个改变的理由


要点

———————————————————————————————————————————————————

  • 迭代器允许访问聚合的元素,而不需要暴露它的内部结构
  • 迭代器将遍历聚合的工作封装进一个对象中。
  • 当使用迭代器的时候,我们依赖聚合提供遍历。
  • 迭代器提供一个通用的接口,让我们遍历聚合的项,当我们编码使用聚合的项时,就可以使用多态机制。
  • 我们应该努力让一个类分配一个责任。
  • 组合模式提供一个结构,可同时包容个别对象和组合对象。
  • 组合模式允许客户对个别对象以及组合对象一视同仁。
  • 组合结构内的任意对象成为组件,组件可以是组合,也可以是叶节点。
  • 在实现组合模式时,有许多设计上的折衷。你要根据需要平衡透明性和安全性。

例子1

———————————————————————————————————————————————————

自定义迭代器

Iterator

package dinermerger;

/**
 * 自定义迭代器接口
 * @author wwj
 *
 */
public interface Iterator {
	boolean hasNext();		//是否还有下一个元素
	Object next();			//返回下一个元素
}


实现迭代器

DinerMenuIterator

package dinermerger;

/**
 * 实现一个具体的迭代器,为餐厅菜单服务
 * @author Administrator
 *
 */
public class DinerMenuIterator implements Iterator {
	MenuItem[] items;
	int position = 0;	//记录当前数组遍历的位置
	
	public DinerMenuIterator(MenuItem[] items) {
		this.items = items;
	}

	@Override
	public boolean hasNext() {
		if(position >= items.length || items[position] == null) {
			return false;
		} else {
			return true;
		}
	}

	@Override
	public Object next() {
		MenuItem menuItem = items[position];
		position = position + 1;
		return menuItem;
	}

}


PancakeHouseMenuIterator

package dinermerger;

import java.util.ArrayList;

/**
 * 煎饼屋菜单实现
 * @author wwj
 *
 */
public class PancakeHouseMenuIterator implements Iterator{
	ArrayList menuItems;
	int position = 0;
	
	public PancakeHouseMenuIterator(ArrayList menuItems) {
		this.menuItems = menuItems;
	}

	@Override
	public boolean hasNext() {
		if(position >= menuItems.size()) {
			return false;
		} else {
			return true;
		}
	}

	@Override
	public Object next() {
		Object object = menuItems.get(position);
		position = position + 1;
		return object;
	}
}


菜单项

package dinermerger;

/**
 * 菜单项
 * @author wwj
 *
 */
public class MenuItem {
	String name;		//名称
	String description;	//叙述
	boolean vegetarian;	//是否为素食
	double price;		//价格
	
	/*
	 * 将这些值传入构造器来初始化这个菜单项
	 */
	public MenuItem(String name, String description, boolean vegetarian,
			double price) {
		this.name = name;
		this.description = description;
		this.vegetarian = vegetarian;
		this.price = price;
	}

	public String getName() {
		return name;
	}

	public String getDescription() {
		return description;
	}

	public double getPrice() {
		return price;
	}

	public boolean isVegetarian() {
		return vegetarian;
	}
	
	
	
}


菜单

PancakeHouseMenu

package dinermerger;

import java.util.ArrayList;

/**
 * 煎饼屋菜单实现
 * @author wwj
 *
 */
public class PancakeHouseMenu {
	ArrayList menuItems;
	public PancakeHouseMenu() {
		menuItems = new ArrayList();
		
		addItem("K&B's Pancake Breakfast", "Pancakes with scrambled eggs, and toast", true, 2.99);
		
		addItem("Regular Pancake Breakfast", "Pancakes with fried eggs, sausage", false, 2.99);
		
		addItem("Blueberry Pancakes", "Pancakes made with fresh blueberries", true, 3.49);
		
		addItem("Waffles", "Waffles, with your choice of blueberries or strawberries", true, 3.59);
		
	}
	
	/**
	 * 创建一个新的菜单项对象,传入每一个变量,然后将它加入到ArrayList中
	 * @param name	菜名
	 * @param description 叙述
	 * @param vegetarian  是否为素食
	 * @param price	价格
	 */
	public void addItem(String name, String description, boolean vegetarian, double price) {
		MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
		menuItems.add(menuItem);
	}
	
/*	public ArrayList getMenuItems() {
		return menuItems;
	}*/
	
	
	public Iterator createIterator() {
		return new PancakeHouseMenuIterator(menuItems);
	}
}



DinerMenu

package dinermerger;

/**
 * 餐厅菜单
 * @author wwj
 *
 */
public class DinerMenu {
	static final int MAX_ITEMS = 6;
	int numberOfItems = 0;
	MenuItem[] menuItems;		//使用一个数组,所以可以控制菜单的长度,并且在取出菜单项的时候,不需要转型
	
	
	public DinerMenu() {
		menuItems = new MenuItem[MAX_ITEMS];
		addItem("Vegetarian BLT",
				"(Fakin') Bacon with lettuce & tomato on Whole wheat", true,
				2.99);

		addItem("BLT", "Bacon with lettuce & tomato on Whole wheat", false,
				2.99);

		addItem("Soup of the day",
				"Soup of the day, with a side of potato salad", false, 3.29);

		addItem("Hotdog",
				"A hot dog, with saurkraut, relish, onions, topped with cheese",
				false, 3.05);

		addItem("Steamed Veggies and Brown Rice",
				"Steamed vegetables over brown rice", true, 3.99);
		addItem("Pasta",
				"Spaghetti with Marinara Sauce, and a slice of sourdough bread",
				true, 3.89);
	}


	
	private void addItem(String name, String description, boolean vegetarian, double price) {
		MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
		if(numberOfItems >= MAX_ITEMS) {
			System.err.println("Sorry, menu is full! Can't add item to menu");
		} else {
			menuItems[numberOfItems] = menuItem;
			numberOfItems = numberOfItems + 1;
		}
	}
	
	
	
	/**
	 * 增加了迭代器之后,这个方法就不需要了
	 * @return
	 */
	/*public MenuItem[] getMenuItems() {
		return menuItems;
	}*/
	
	
	/**
	 * 用来从菜单项数组创建一个DinerMenuIterator,并将它返回给客户
	 */
	public Iterator createIterator() {
		return new DinerMenuIterator(menuItems);
	}
	
}


女招待

package dinermerger;

/**
 * 女招待类
 * @author wwj
 *
 */
public class Waitress {
	PancakeHouseMenu pancakeHouseMenu;
	DinerMenu dinerMenu;
	
	/**
	 *在这个构造器中,女招待照顾两个菜单
	 * @param pancakeHouseMenu
	 * @param dinerMenu
	 */
	public Waitress(PancakeHouseMenu pancakeHouseMenu, DinerMenu dinerMenu) {
		this.pancakeHouseMenu = pancakeHouseMenu;
		this.dinerMenu = dinerMenu;
	}
	
	public void printMenu() {
		Iterator pancakeIterator = pancakeHouseMenu.createIterator();
		Iterator dinerIterator = dinerMenu.createIterator();
		System.out.println("MENU
----
BREAKFAST");
		printMenu(pancakeIterator);
		System.out.println("
LUNCH");
		printMenu(dinerIterator);
	}

	private void printMenu(Iterator iterator) {
		while(iterator.hasNext()) {	//测试是否还有其他项
			MenuItem menuItem = (MenuItem) iterator.next();
			System.out.print(menuItem.getName() + ", ");
			System.out.print(menuItem.getPrice() + " -- ");
			System.out.println(menuItem.getDescription());
		}
	}
}


测试

package dinermerger;

public class MenuTestDrive {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		PancakeHouseMenu pancakeHouseMenu = new PancakeHouseMenu();
		DinerMenu dinerMenu = new DinerMenu();
		
		Waitress waitress = new Waitress(pancakeHouseMenu, dinerMenu);
		
		waitress.printMenu();
	}

}


结果:

MENU
----
BREAKFAST
K&B's Pancake Breakfast, 2.99 -- Pancakes with scrambled eggs, and toast
Regular Pancake Breakfast, 2.99 -- Pancakes with fried eggs, sausage
Blueberry Pancakes, 3.49 -- Pancakes made with fresh blueberries
Waffles, 3.59 -- Waffles, with your choice of blueberries or strawberries


LUNCH
Vegetarian BLT, 2.99 -- (Fakin') Bacon with lettuce & tomato on Whole wheat
BLT, 2.99 -- Bacon with lettuce & tomato on Whole wheat
Soup of the day, 3.29 -- Soup of the day, with a side of potato salad
Hotdog, 3.05 -- A hot dog, with saurkraut, relish, onions, topped with cheese
Steamed Veggies and Brown Rice, 3.99 -- Steamed vegetables over brown rice
Pasta, 3.89 -- Spaghetti with Marinara Sauce, and a slice of sourdough bread



例子2

———————————————————————————————————————————————————

利用java.util.Iterator来实现迭代器

提供一个Menu接口,让PancakeHouseMenu和DinerMenu都实现Menu接口,这样Waitress就不用依赖具体的菜单的问题,也不用依赖菜单项的具体实现了。


package dinermerger;

/**
 * 这是一个简单的接口,让客户能够取得菜单项
 * @author Administrator
 *
 */
public interface Menu {
	public Iterator createIterator();
}


DinerMenu

package dinermerger;

import java.util.Iterator;

/**
 * 餐厅菜单
 * @author wwj
 *
 */
public class DinerMenu implements Menu{
	static final int MAX_ITEMS = 6;
	int numberOfItems = 0;
	MenuItem[] menuItems;		//使用一个数组,所以可以控制菜单的长度,并且在取出菜单项的时候,不需要转型
	
	
	public DinerMenu() {
		menuItems = new MenuItem[MAX_ITEMS];
		addItem("Vegetarian BLT",
				"(Fakin') Bacon with lettuce & tomato on Whole wheat", true,
				2.99);

		addItem("BLT", "Bacon with lettuce & tomato on Whole wheat", false,
				2.99);

		addItem("Soup of the day",
				"Soup of the day, with a side of potato salad", false, 3.29);

		addItem("Hotdog",
				"A hot dog, with saurkraut, relish, onions, topped with cheese",
				false, 3.05);

		addItem("Steamed Veggies and Brown Rice",
				"Steamed vegetables over brown rice", true, 3.99);
		addItem("Pasta",
				"Spaghetti with Marinara Sauce, and a slice of sourdough bread",
				true, 3.89);
	}


	
	private void addItem(String name, String description, boolean vegetarian, double price) {
		MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
		if(numberOfItems >= MAX_ITEMS) {
			System.err.println("Sorry, menu is full! Can't add item to menu");
		} else {
			menuItems[numberOfItems] = menuItem;
			numberOfItems = numberOfItems + 1;
		}
	}
	
	
	
	/**
	 * 增加了迭代器之后,这个方法就不需要了
	 * @return
	 */
	/*public MenuItem[] getMenuItems() {
		return menuItems;
	}*/
	
	
	/**
	 * 用来从菜单项数组创建一个DinerMenuIterator,并将它返回给客户
	 */
	public Iterator createIterator() {
		return new DinerMenuIterator(menuItems);
	}
	
}


PancakeHouseMenu

不创建自己的迭代器,而是调用ArrayList的iterator()方法

package dinermerger;

import java.util.ArrayList;
import java.util.Iterator;

/**
 * 煎饼屋菜单实现
 * @author wwj
 *
 */
public class PancakeHouseMenu implements Menu{
	ArrayList menuItems;
	public PancakeHouseMenu() {
		menuItems = new ArrayList();
		
		addItem("K&B's Pancake Breakfast", "Pancakes with scrambled eggs, and toast", true, 2.99);
		
		addItem("Regular Pancake Breakfast", "Pancakes with fried eggs, sausage", false, 2.99);
		
		addItem("Blueberry Pancakes", "Pancakes made with fresh blueberries", true, 3.49);
		
		addItem("Waffles", "Waffles, with your choice of blueberries or strawberries", true, 3.59);
		
	}
	
	/**
	 * 创建一个新的菜单项对象,传入每一个变量,然后将它加入到ArrayList中
	 * @param name	菜名
	 * @param description 叙述
	 * @param vegetarian  是否为素食
	 * @param price	价格
	 */
	public void addItem(String name, String description, boolean vegetarian, double price) {
		MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
		menuItems.add(menuItem);
	}
	
/*	public ArrayList getMenuItems() {
		return menuItems;
	}*/
	
	
	public Iterator createIterator() {
		return menuItems.iterator();
	}
}


DinerMenuIterator

package dinermerger;

import java.util.Iterator;

/**
 * 实现一个具体的迭代器,为餐厅菜单服务
 * @author Administrator
 *
 */
public class DinerMenuIterator implements Iterator {
	MenuItem[] items;
	int position = 0;	//记录当前数组遍历的位置
	
	public DinerMenuIterator(MenuItem[] items) {
		this.items = items;
	}

	@Override
	public boolean hasNext() {
		if(position >= items.length || items[position] == null) {
			return false;
		} else {
			return true;
		}
	}

	@Override
	public Object next() {
		MenuItem menuItem = items[position];
		position = position + 1;
		return menuItem;
	}

	@Override
	public void remove() {
		if(position <= 0) {
			throw new IllegalStateException("You can't remove an item until you've done at least on next()");
		}
		if(items[position - 1] != null) {
			for(int i = position - 1; i < (items.length - 1); i++) {
				items[i] = items[i + 1];
			}
			items[items.length - 1] = null;
		}
		
	}

}


Waitress

package dinermerger;

import java.util.Iterator; 

/**
 * 女招待类
 * @author wwj
 *
 */
public class Waitress {
//	PancakeHouseMenu pancakeHouseMenu;
//	DinerMenu dinerMenu;
	Menu pancakeHouseMenu;
	Menu dinerMenu;
	
	/**
	 *在这个构造器中,女招待照顾两个菜单
	 * @param pancakeHouseMenu
	 * @param dinerMenu
	 */
	public Waitress(Menu pancakeHouseMenu, Menu dinerMenu) {
		this.pancakeHouseMenu = pancakeHouseMenu;
		this.dinerMenu = dinerMenu;
	}
	
	public void printMenu() {
		Iterator pancakeIterator = pancakeHouseMenu.createIterator();
		Iterator dinerIterator = dinerMenu.createIterator();
		System.out.println("MENU
----
BREAKFAST");
		printMenu(pancakeIterator);
		System.out.println("
LUNCH");
		printMenu(dinerIterator);
	}

	private void printMenu(Iterator iterator) {
		while(iterator.hasNext()) {	//测试是否还有其他项
			MenuItem menuItem = (MenuItem) iterator.next();
			System.out.print(menuItem.getName() + ", ");
			System.out.print(menuItem.getPrice() + " -- ");
			System.out.println(menuItem.getDescription());
		}
	}
}


增加一个CafeMenu会变成以下这样

package dinermerger;

import java.util.Hashtable;
import java.util.Iterator;

/**
 * 咖啡厅菜单
 * @author wwj
 *
 */
public class CafeMenu implements Menu{
	Hashtable menuItems = new Hashtable();
	
	public CafeMenu() {
		addItem("Veggie Burger and Air Fries",
				"Veggie burger on a whole wheat bun, lettuce, tomato, and fries",
				true, 3.99);
		addItem("Soup of the day",
				"A cup of the soup of the day, with a side salad", false, 3.69);
		addItem("Burrito",
				"A large burrito, with whole pinto beans, salsa, guacamole",
				true, 4.29);
	}
	
	
	public void addItem(String name, String description, boolean vegetarian, double price) {
		MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
		menuItems.put(menuItem.getName(), menuItem);
	}


	@Override
	public Iterator createIterator() {
		return menuItems.values().iterator();
	}
}


package dinermerger;

import java.util.Iterator; 

/**
 * 女招待类
 * @author wwj
 *
 */
public class Waitress {
//	PancakeHouseMenu pancakeHouseMenu;
//	DinerMenu dinerMenu;
	Menu pancakeHouseMenu;
	Menu dinerMenu;
	Menu cafeMenu;	
	
	/**
	 *在这个构造器中,女招待照顾两个菜单
	 * @param pancakeHouseMenu
	 * @param dinerMenu
	 */
	public Waitress(Menu pancakeHouseMenu, Menu dinerMenu) {
		this.pancakeHouseMenu = pancakeHouseMenu;
		this.dinerMenu = dinerMenu;
	}
	
	/**
	 * 新增一个cafeMenu
	 * @param pancakeHouseMenu
	 * @param dinerMenu
	 * @param cafeMenu
	 */
	public Waitress(Menu pancakeHouseMenu, Menu dinerMenu, Menu cafeMenu) {
		this.pancakeHouseMenu = pancakeHouseMenu;
		this.dinerMenu = dinerMenu;
		this.cafeMenu = cafeMenu;
	}



	public void printMenu() {
		Iterator pancakeIterator = pancakeHouseMenu.createIterator();
		Iterator dinerIterator = dinerMenu.createIterator();
		Iterator cafeIterator = cafeMenu.createIterator();
		System.out.println("MENU
----
BREAKFAST");
		printMenu(pancakeIterator);
		System.out.println("
LUNCH");
		printMenu(dinerIterator);
		System.out.println("
DINNER");
		printMenu(cafeIterator);
	}

	private void printMenu(Iterator iterator) {
		while(iterator.hasNext()) {	//测试是否还有其他项
			MenuItem menuItem = (MenuItem) iterator.next();
			System.out.print(menuItem.getName() + ", ");
			System.out.print(menuItem.getPrice() + " -- ");
			System.out.println(menuItem.getDescription());
		}
	}
}


Test

package dinermerger;

public class MenuTestDrive {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
//		PancakeHouseMenu pancakeHouseMenu = new PancakeHouseMenu();
//		DinerMenu dinerMenu = new DinerMenu();
//		
//		Waitress waitress = new Waitress(pancakeHouseMenu, dinerMenu);
//		
//		waitress.printMenu();
		
		Menu pancakeHouseMenu = new PancakeHouseMenu();
		Menu dinerMenu = new DinerMenu();
		Menu cafeMenu = new CafeMenu();
		
		Waitress waitress = new Waitress(pancakeHouseMenu, dinerMenu, cafeMenu);
		waitress.printMenu();
	}

}


结果:

MENU
----
BREAKFAST
K&B's Pancake Breakfast, 2.99 -- Pancakes with scrambled eggs, and toast
Regular Pancake Breakfast, 2.99 -- Pancakes with fried eggs, sausage
Blueberry Pancakes, 3.49 -- Pancakes made with fresh blueberries
Waffles, 3.59 -- Waffles, with your choice of blueberries or strawberries


LUNCH
Vegetarian BLT, 2.99 -- (Fakin') Bacon with lettuce & tomato on Whole wheat
BLT, 2.99 -- Bacon with lettuce & tomato on Whole wheat
Soup of the day, 3.29 -- Soup of the day, with a side of potato salad
Hotdog, 3.05 -- A hot dog, with saurkraut, relish, onions, topped with cheese
Steamed Veggies and Brown Rice, 3.99 -- Steamed vegetables over brown rice
Pasta, 3.89 -- Spaghetti with Marinara Sauce, and a slice of sourdough bread


DINNER
Soup of the day, 3.69 -- A cup of the soup of the day, with a side salad
Burrito, 4.29 -- A large burrito, with whole pinto beans, salsa, guacamole
Veggie Burger and Air Fries, 3.99 -- Veggie burger on a whole wheat bun, lettuce, tomato, and fries


为了让女招待更加有扩展性,我们这样做

package dinermerger;

import java.util.ArrayList;
import java.util.Iterator; 

/**
 * 女招待类
 * @author wwj
 *
 */
public class Waitress {
//	PancakeHouseMenu pancakeHouseMenu;
//	DinerMenu dinerMenu;
//	Menu pancakeHouseMenu;
//	Menu dinerMenu;
//	Menu cafeMenu;	
	ArrayList menus;
	
/*	*//**
	 *在这个构造器中,女招待照顾两个菜单
	 * @param pancakeHouseMenu
	 * @param dinerMenu
	 *//*
	public Waitress(Menu pancakeHouseMenu, Menu dinerMenu) {
		this.pancakeHouseMenu = pancakeHouseMenu;
		this.dinerMenu = dinerMenu;
	}
	
	*//**
	 * 新增一个cafeMenu
	 * @param pancakeHouseMenu
	 * @param dinerMenu
	 * @param cafeMenu
	 *//*
	public Waitress(Menu pancakeHouseMenu, Menu dinerMenu, Menu cafeMenu) {
		this.pancakeHouseMenu = pancakeHouseMenu;
		this.dinerMenu = dinerMenu;
		this.cafeMenu = cafeMenu;
	}*/

	public Waitress(ArrayList menus) {
		this.menus = menus;
	}



	public void printMenu() {
/*		Iterator pancakeIterator = pancakeHouseMenu.createIterator();
		Iterator dinerIterator = dinerMenu.createIterator();
		Iterator cafeIterator = cafeMenu.createIterator();
		System.out.println("MENU
----
BREAKFAST");
		printMenu(pancakeIterator);
		System.out.println("
LUNCH");
		printMenu(dinerIterator);
		System.out.println("
DINNER");
		printMenu(cafeIterator);*/
		Iterator menuIterator = menus.iterator();
		while(menuIterator.hasNext()) {
			Menu menu = (Menu)menuIterator.next();
			printMenu(menu.createIterator());
		}
		
	}

	
	private void printMenu(Iterator iterator) {
		while(iterator.hasNext()) {	//测试是否还有其他项
			MenuItem menuItem = (MenuItem) iterator.next();
			System.out.print(menuItem.getName() + ", ");
			System.out.print(menuItem.getPrice() + " -- ");
			System.out.println(menuItem.getDescription());
		}
	}
}


测试的时候我们就可以这样

package dinermerger;

import java.util.ArrayList;

public class MenuTestDrive {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
//		PancakeHouseMenu pancakeHouseMenu = new PancakeHouseMenu();
//		DinerMenu dinerMenu = new DinerMenu();
//		
//		Waitress waitress = new Waitress(pancakeHouseMenu, dinerMenu);
//		
//		waitress.printMenu();
		
		Menu pancakeHouseMenu = new PancakeHouseMenu();
		Menu dinerMenu = new DinerMenu();
		Menu cafeMenu = new CafeMenu();
		
//		Waitress waitress = new Waitress(pancakeHouseMenu, dinerMenu, cafeMenu);
		ArrayList menus = new ArrayList();
		menus.add(pancakeHouseMenu);
		menus.add(dinerMenu);
		menus.add(cafeMenu);
		Waitress waitress = new Waitress(menus);
		waitress.printMenu();
	}

}


总算是要讲到组合模式了,这个模式可以解决迭代器模式中不能解决的一个难题。比如我们需要一个新的餐单,菜单下又有子菜单,单单用迭代器就不能解决了。这时候可以考虑到用树形结构来展示整个菜单。

看下面的例子吧:

定义菜单组件

package composite;

/**
 * 定义菜单组件
 * @author Administrator
 *
 */
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 getDescription() {
		throw new UnsupportedOperationException();
	}
	public double getPrice() {
		throw new UnsupportedOperationException();
	}
	public boolean isVegetarian() {
		throw new UnsupportedOperationException();
	}
  
	public void print() {
		throw new UnsupportedOperationException();
	}
}


实现菜单

package composite;

import java.util.ArrayList;
import java.util.Iterator;

public class Menu extends MenuComponent{
	ArrayList menuComponents = new ArrayList();
	String name;
	String description;
	
	public Menu(String name, String description) {
		this.name = name;
		this.description = description;
	}
	
	
	public void add(MenuComponent menuComponent) {
		menuComponents.add(menuComponent);
	}
	
	public void remove(MenuComponent menuComponent) {
		menuComponents.remove(menuComponent);
	}
	
	public MenuComponent getChild(int i) {
		return (MenuComponent) menuComponents.get(i);
	}


	public String getName() {
		return name;
	}


	public String getDescription() {
		return description;
	}
	
	
	public void print(){
		System.out.print("
" + getName());
		System.out.println(", " + getDescription());
		System.out.println("------------------");
		
		Iterator iterator = menuComponents.iterator();
		while(iterator.hasNext()) {
			MenuComponent menuComponent =
				(MenuComponent) iterator.next();
			menuComponent.print();
		}
	}
}


实现菜单项

package composite;

/**
 * 实现菜单项
 * @author Administrator
 *
 */
public class MenuItem extends MenuComponent{
	String name;
	String description;
	boolean vegetarian;
	double price;
	
	public MenuItem(String name, String description, boolean vegetarian,
			double price) {
		this.name = name;
		this.description = description;
		this.vegetarian = vegetarian;
		this.price = price;
	}

	public String getName() {
		return name;
	}

	public String getDescription() {
		return description;
	}

	public boolean isVegetarian() {
		return vegetarian;
	}

	public double getPrice() {
		return price;
	}
	
	
	public void print(){
		System.out.print("  " + getName());
		if(isVegetarian()) {
			System.out.print("(v)");
		}
		System.out.println("," + getPrice());
		System.out.println("    --" + getDescription());
	}
	
	
}


变得十分快乐的女招待

package composite;

import java.util.Iterator;
  
public class Waitress {
	MenuComponent allMenus;
 
	public Waitress(MenuComponent allMenus) {
		this.allMenus = allMenus;
	}
 
	public void printMenu() {
		allMenus.print();
	}
}


我们这样测试

package composite;

import java.util.*;

public class MenuTestDrive {
	public static void main(String args[]) {
		MenuComponent pancakeHouseMenu = 
			new Menu("PANCAKE HOUSE MENU", "Breakfast");
		MenuComponent dinerMenu = 
			new Menu("DINER MENU", "Lunch");
		MenuComponent cafeMenu = 
			new Menu("CAFE MENU", "Dinner");
		MenuComponent dessertMenu = 
			new Menu("DESSERT MENU", "Dessert of course!");
		MenuComponent coffeeMenu = new Menu("COFFEE MENU", "Stuff to go with your afternoon coffee");
  
		MenuComponent allMenus = new Menu("ALL MENUS", "All menus combined");
  
		allMenus.add(pancakeHouseMenu);
		allMenus.add(dinerMenu);
		allMenus.add(cafeMenu);
  
		pancakeHouseMenu.add(new MenuItem(
			"K&B's Pancake Breakfast", 
			"Pancakes with scrambled eggs, and toast", 
			true,
			2.99));
		pancakeHouseMenu.add(new MenuItem(
			"Regular Pancake Breakfast", 
			"Pancakes with fried eggs, sausage", 
			false,
			2.99));
		pancakeHouseMenu.add(new MenuItem(
			"Blueberry Pancakes",
			"Pancakes made with fresh blueberries, and blueberry syrup",
			true,
			3.49));
		pancakeHouseMenu.add(new MenuItem(
			"Waffles",
			"Waffles, with your choice of blueberries or strawberries",
			true,
			3.59));

		dinerMenu.add(new MenuItem(
			"Vegetarian BLT",
			"(Fakin') Bacon with lettuce & tomato on whole wheat", 
			true, 
			2.99));
		dinerMenu.add(new MenuItem(
			"BLT",
			"Bacon with lettuce & tomato on whole wheat", 
			false, 
			2.99));
		dinerMenu.add(new MenuItem(
			"Soup of the day",
			"A bowl of the soup of the day, with a side of potato salad", 
			false, 
			3.29));
		dinerMenu.add(new MenuItem(
			"Hotdog",
			"A hot dog, with saurkraut, relish, onions, topped with cheese",
			false, 
			3.05));
		dinerMenu.add(new MenuItem(
			"Steamed Veggies and Brown Rice",
			"Steamed vegetables over brown rice", 
			true, 
			3.99));
 
		dinerMenu.add(new MenuItem(
			"Pasta",
			"Spaghetti with Marinara Sauce, and a slice of sourdough bread",
			true, 
			3.89));
   
		dinerMenu.add(dessertMenu);
  
		dessertMenu.add(new MenuItem(
			"Apple Pie",
			"Apple pie with a flakey crust, topped with vanilla icecream",
			true,
			1.59));
  
		dessertMenu.add(new MenuItem(
			"Cheesecake",
			"Creamy New York cheesecake, with a chocolate graham crust",
			true,
			1.99));
		dessertMenu.add(new MenuItem(
			"Sorbet",
			"A scoop of raspberry and a scoop of lime",
			true,
			1.89));

		cafeMenu.add(new MenuItem(
			"Veggie Burger and Air Fries",
			"Veggie burger on a whole wheat bun, lettuce, tomato, and fries",
			true, 
			3.99));
		cafeMenu.add(new MenuItem(
			"Soup of the day",
			"A cup of the soup of the day, with a side salad",
			false, 
			3.69));
		cafeMenu.add(new MenuItem(
			"Burrito",
			"A large burrito, with whole pinto beans, salsa, guacamole",
			true, 
			4.29));

		cafeMenu.add(coffeeMenu);

		coffeeMenu.add(new MenuItem(
			"Coffee Cake",
			"Crumbly cake topped with cinnamon and walnuts",
			true,
			1.59));
		coffeeMenu.add(new MenuItem(
			"Bagel",
			"Flavors include sesame, poppyseed, cinnamon raisin, pumpkin",
			false,
			0.69));
		coffeeMenu.add(new MenuItem(
			"Biscotti",
			"Three almond or hazelnut biscotti cookies",
			true,
			0.89));
 
		Waitress waitress = new Waitress(allMenus);
   
		waitress.printMenu();
	}
}


测试结果:



ALL MENUS, All menus combined
------------------


PANCAKE HOUSE MENU, Breakfast
------------------
  K&B's Pancake Breakfast(v),2.99
    --Pancakes with scrambled eggs, and toast
  Regular Pancake Breakfast,2.99
    --Pancakes with fried eggs, sausage
  Blueberry Pancakes(v),3.49
    --Pancakes made with fresh blueberries, and blueberry syrup
  Waffles(v),3.59
    --Waffles, with your choice of blueberries or strawberries


DINER MENU, Lunch
------------------
  Vegetarian BLT(v),2.99
    --(Fakin') Bacon with lettuce & tomato on whole wheat
  BLT,2.99
    --Bacon with lettuce & tomato on whole wheat
  Soup of the day,3.29
    --A bowl of the soup of the day, with a side of potato salad
  Hotdog,3.05
    --A hot dog, with saurkraut, relish, onions, topped with cheese
  Steamed Veggies and Brown Rice(v),3.99
    --Steamed vegetables over brown rice
  Pasta(v),3.89
    --Spaghetti with Marinara Sauce, and a slice of sourdough bread


DESSERT MENU, Dessert of course!
------------------
  Apple Pie(v),1.59
    --Apple pie with a flakey crust, topped with vanilla icecream
  Cheesecake(v),1.99
    --Creamy New York cheesecake, with a chocolate graham crust
  Sorbet(v),1.89
    --A scoop of raspberry and a scoop of lime


CAFE MENU, Dinner
------------------
  Veggie Burger and Air Fries(v),3.99
    --Veggie burger on a whole wheat bun, lettuce, tomato, and fries
  Soup of the day,3.69
    --A cup of the soup of the day, with a side salad
  Burrito(v),4.29
    --A large burrito, with whole pinto beans, salsa, guacamole


COFFEE MENU, Stuff to go with your afternoon coffee
------------------
  Coffee Cake(v),1.59
    --Crumbly cake topped with cinnamon and walnuts
  Bagel,0.69
    --Flavors include sesame, poppyseed, cinnamon raisin, pumpkin
  Biscotti(v),0.89
    --Three almond or hazelnut biscotti cookies

原文地址:https://www.cnblogs.com/xinyuyuanm/p/3177778.html