设计模式 组合与迭代器

迭代器模式:提供一种方法顺序访问遍历一个聚合(集合)对象中的各个元素,而无需暴露其(集合)内部的实现。

组合模式: 允许将对象组成树形结构来表现“整体/部分”的层次结构,该树形结构可同时包容个别对象和组合对象。组合让客户以一致的方式处理个别对象和组合对象。组合结构内的任意对象称为组件,组件可以是组合,也可以是叶节点(无法再分)。

下面以一个实例说明:

1. 主函数

public class MenuTestDrive {

	/**
	 * @param args
	 * 组合模式:允许你将对象组合成树形结构来表现“整体/部分”层次结构,树形结构包含了组合以及个别对象。
	 * 组合能够让客户以一致的方式处理个别对象以及对象组合。迭代器模式是解决方案中的一部分。
	 * 组合包含组件,组件有两种:组合与叶节点元素。
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		MenuComponent pancakeHouseMenu = new Menu("PANCAKE HOUSE MENU","Breakfast");
		MenuComponent dinerMenu = new Menu("DINER MENU","Lunch");
		MenuComponent cafeMeun = new Menu("CAFE MENU","Dinner");
		MenuComponent dessertMenu = new Menu("DESSERT MENU","Dessert of course!");
		MenuComponent allMenus = new Menu("ALL MENUS","All menus combined");

		System.out.println("------------------MenuTestDrive main() add differents MenuComponent to allMenus start----------------------");
		try{
		allMenus.add(pancakeHouseMenu);
		allMenus.add(dinerMenu);
		allMenus.add(cafeMeun);

		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 ice cream",
				true,
				1.59));
		} catch (Exception e){
			e.printStackTrace();
		}

		System.out.println("------------------MenuTestDrive main() add differents MenuComponent to allMenus end -----------------------");
		Waitress waitress = new Waitress(allMenus);
		System.out.println("------------------case 1: Waitress not care of how to visit , only use MenuComponent to call interface-----");
		waitress.printMenu();
		System.out.println("------------------case 2: Waitress use Composite-Iterator mode to filter all 蔬菜vegetarians----------------");
		waitress.printVegetarianMenu();

	}


}
2.  抽象组件 MenuComponent.java

import java.util.Iterator;

public abstract class MenuComponent {

	public void add(MenuComponent menuComponent)
			throws UnsupportOperationException {
		throw new UnsupportOperationException();
	}

	public void remove(MenuComponent menuComponent)
			throws UnsupportOperationException {
		throw new UnsupportOperationException();
	}

	public MenuComponent getChild(int i) throws UnsupportOperationException {
		throw new UnsupportOperationException();
	}

	public String getName() throws UnsupportOperationException {
		throw new UnsupportOperationException();
	}

	public String getDescription() throws UnsupportOperationException {
		throw new UnsupportOperationException();
	}

	public double getPrice() throws UnsupportOperationException {
		throw new UnsupportOperationException();
	}

	public boolean isVegetarian() throws UnsupportOperationException {
		throw new UnsupportOperationException();
	}

	public void print() throws UnsupportOperationException {
		throw new UnsupportOperationException();
	}

	abstract Iterator createIterator();
}
3. 抽象组件的子类:叶节点MenuItem 和组合Menu 

3.1 叶节点组件MenuItem.java

import java.util.Iterator;

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() throws UnsupportOperationException {
		// TODO Auto-generated method stub
		return name;
	}

	public String getDescription() throws UnsupportOperationException {
		// TODO Auto-generated method stub
		return description;
	}

	public double getPrice() throws UnsupportOperationException {
		// TODO Auto-generated method stub
		return price;
	}

	public boolean isVegetarian() throws UnsupportOperationException {
		// TODO Auto-generated method stub
		return vegetarian;
	}

	public void print() throws UnsupportOperationException {
		// TODO Auto-generated method stub
		System.out.print("  " + getName());
		if (isVegetarian()) {
			System.out.print(" (V) ");
		}
		System.out.print(" , " + getPrice());
		System.out.println("    --" + getDescription());
	}

	Iterator createIterator() {
		// TODO Auto-generated method stub
		return new NullIterator();
	}
}
3.2 组合组件Menu.java

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)
			throws UnsupportOperationException {
		// TODO Auto-generated method stub
		menuComponents.add(menuComponent);
	}

	public void remove(MenuComponent menuComponent)
			throws UnsupportOperationException {
		// TODO Auto-generated method stub
		menuComponents.remove(menuComponent);
	}

	public MenuComponent getChild(int i) throws UnsupportOperationException {
		// TODO Auto-generated method stub
		return (MenuComponent) menuComponents.get(i);
	}

	public String getName() throws UnsupportOperationException {
		// TODO Auto-generated method stub
		return name;
	}

	public String getDescription() throws UnsupportOperationException {
		// TODO Auto-generated method stub
		return description;
	}

	public void print() throws UnsupportOperationException {
		// TODO Auto-generated method stub
		System.out.print("\n" + getName());
		System.out.println("  ," + getDescription());
		System.out.println(" ----------------");

		// 如果我们想要女招待可以使用迭代器变流器整个组合,就不需要在此处使用迭代器遍历,要交给女招待
		Iterator it = menuComponents.iterator();
		while (it.hasNext()) {
			MenuComponent menuCompent = (MenuComponent) it.next();
			menuCompent.print();
		}
	}

	// 为了女招待使用迭代器遍历组合,创建该接口
	Iterator createIterator() {
		// TODO Auto-generated method stub
		return new CompositeIterator(menuComponents.iterator());
	}

}

4.  实现Iterator迭代器的子类NullIterator.java和CompositeIterator.java

4.1  叶子节点使用createIterator创建NullIterator 迭代器

import java.util.Iterator;

public class NullIterator implements Iterator {

	public boolean hasNext() {
		// TODO Auto-generated method stub
		return false;
	}

	public Object next() {
		// TODO Auto-generated method stub
		return null;
	}

	public void remove() {
		// TODO Auto-generated method stub
		throw new UnsupportedOperationException();
	}

}

4.2 组合组件使用createIterator创建CompositeIterator 迭代器

  该迭代器可遍历组合组件内的所有组件(叶子节点组件和组合组件,子组合组件....)

import java.util.Iterator;
import java.util.Stack;
import java.util.function.Consumer;

// 这是我们创建的便于女招待使用迭代器遍历组合的“组合迭代器”类
// 它的工作是遍历组件内的菜单项,并确保所有的子菜单(以及子子菜单....)都被包括进来
public class CompositeIterator implements Iterator {

	Stack stack = new Stack();

	// iterator参数是 Menu对象(组合)中的成员ArrayList对象取得的迭代器
	public CompositeIterator(Iterator iterator) {
		stack.push(iterator);
	}

	public boolean hasNext() {
		// TODO Auto-generated method stub
		if (stack.isEmpty()) {
			return false;
		} else {
			Iterator iterator = (Iterator) stack.peek(); // 取出来这个迭代器偷看一下
			if (iterator.hasNext()) {
				return true;
			} else {
				stack.pop(); // 将遍历完的迭代器对象弹出堆栈
				return hasNext();
			}
		}
	}

	public Object next() {
		// TODO Auto-generated method stub
		if (hasNext()) {
			Iterator iterator = (Iterator) stack.peek(); // 取出堆栈存放的迭代器偷看一下
			MenuComponent component = (MenuComponent) iterator.next();// 取出该位置对象,并将位置移动到下一个
			if (component instanceof Menu) {
				stack.push(component.createIterator()); // 如果是子菜单(组合类型),把将要遍历的下一个迭代器对象放入到堆栈,为了下一步的遍历
			}
			return component;
		}
		return null;
	}

	public void remove() {
		// TODO Auto-generated method stub
		throw new UnsupportedOperationException();
	}

}
5. 自定义异常类UnsupportOperationException
public class UnsupportOperationException extends Exception {

	private static final long serialVersionUID = 1L;

	UnsupportOperationException() {
	}
}
6. 女招待对象Waitress,她有两种需求:不关注一个个去遍历,调用组合组件的接口一次完成;关注如何使用迭代器访问,并筛选出叶子节点做相应operation

import java.util.Iterator;

public class Waitress {
	MenuComponent allMenus;

	public Waitress(MenuComponent allMenus) {
		this.allMenus = allMenus;
	}

	// 这个接口是女招待调用打印接口,实际是在组合内部打印方法调用迭代器的,女招待不能随意取出任何
	public void printMenu() {
		try {
			allMenus.print();
		} catch (UnsupportOperationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	// 这个接口是用让女招待使用迭代器去遍历组合的,可以随意取出对象
	public void printVegetarianMenu() {
		Iterator iterator = allMenus.createIterator();
		System.out.println("\n VEGETARIAN MENU\n----");
		while (iterator.hasNext()) {
			MenuComponent menuCompent = (MenuComponent) iterator.next();
			try {
				if (menuCompent.isVegetarian()) {
					menuCompent.print();
				}
			} catch (UnsupportOperationException e) {
				// TODO Auto-generated catch block
				// e.printStackTrace();
			}

		}

	}
}

7. 类结构层次:

Menu 和 MenuItem均继承 MenuComponent组件抽象类。

CompositeIterator和NullIterator均实现java内置接口 Iterator。

组合模式的树结构:

                                                                Menu

                                                    --                 --      --

                                                --                        ---          ----

                                           MenuItem            MenuItem      Menu

                                                                                                --

                                                                                            --

                                                                                        MenuItem

可以无限扩张。
图片1: 结构类图   

111111111

图片2:调用图

22222222
运行后结果:

------------------MenuTestDrive main() add differents MenuComponent to allMenus start----------------------
------------------MenuTestDrive main() add differents MenuComponent to allMenus end -----------------------
------------------case 1: Waitress not care of how to visit , only use MenuComponent to call interface-----


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


PANCAKE HOUSE MENU  ,Breakfast
 ----------------


DINER MENU  ,Lunch
 ----------------
  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 ice cream


CAFE MENU  ,Dinner
 ----------------
------------------case 2: Waitress use Composite-Iterator mode to filter all 蔬菜vegetarians----------------


 VEGETARIAN MENU
----
  Pasta (V)  , 3.89    --Spaghetti with Marinara Sauce, and a slice of sourdough bread
  Apple Pie (V)  , 1.59    --Apple Pie with a flakey crust, topped with vanilla ice cream
  Apple Pie (V)  , 1.59    --Apple Pie with a flakey crust, topped with vanilla ice cream

猜你喜欢

转载自blog.csdn.net/snail201211/article/details/78972189