`

《Head.First设计模式》的学习笔记(13)--组合模式

 
阅读更多

先说一下题外话,这个模式是我学的最累的模式,代码纠结无比,而且似乎又不经常用,但是我还是硬着头皮把这个模式给看完了。废话不多说,开始干活.......

意图:允许你将对象组成属性结构来表现“整体/部分”的层次结构,组合能让客户以一直的方式处理个别的对象和对象组合。

结构:

 



 首先是组合包含组件,组件有两种:组合与叶节点元素。

接着我们继续看例子:

在原有的对象餐厅我们添加了晚餐-咖啡餐厅,而咖啡餐厅却有甜点子菜单,这样原有的迭代器模式就不能顺利解决问题了,我们要使用组合与迭代模式的联合:

首先我们来看组合模式该如何进行:



 

在看具体的代码,从接口MenuComponent开始:

import java.util.*;

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 abstract Iterator createIterator();
 
	public void print() {
		throw new UnsupportedOperationException();
	}
}

 

 

因为菜单是一个组合,我们来看菜单具体的实现代码:

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

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("\n" + getName());
		System.out.println(", " + getDescription());
		System.out.println("---------------------");
  
		Iterator iterator = menuComponents.iterator();
		while (iterator.hasNext()) {
			MenuComponent menuComponent = 
				(MenuComponent)iterator.next();
			menuComponent.print();
		}
	}
}

 

 其中特别注意的是print函数,由于menu菜单是组合我们只能调用菜单组件接口的print方法.

这个我们已经成功在内部使用迭代器,遍历整个目标,但是我们还是需要实现一个功能,就是女Waitress像调用这个迭代器那该如何操作,这时候我们就需要创建一个新的外部迭代器:首先我们要实现两个外部迭代器,一个是NullIteractor另一个是CompositeIterator。

NullIterator 代码:

 

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

 CompositeIterator 代码为:

 

import java.util.*;
  
public class CompositeIterator implements Iterator {
	Stack stack = new Stack();
   
	public CompositeIterator(Iterator iterator) {
		stack.push(iterator);
	}
   
	public Object next() {
		if (hasNext()) {
			Iterator iterator = (Iterator) stack.peek();
			MenuComponent component = (MenuComponent) iterator.next();
			if (component instanceof Menu) {
				stack.push(component.createIterator());
			} 
			return component;
		} else {
			return null;
		}
	}
  
	public boolean hasNext() {
		if (stack.empty()) {
			return false;
		} else {
			Iterator iterator = (Iterator) stack.peek();
			if (!iterator.hasNext()) {
				stack.pop();
				return hasNext();
			} else {
				return true;
			}
		}
	}
   
	public void remove() {
		throw new UnsupportedOperationException();
	}
}

 为什么要实现两个呢?一个是为“叶子”准备的,另一个是为“节点”准备的。

首先在menuItem实现createIteractor()

 

public Iterator createIterator() {
		return new NullIterator();
	}

 然后是menu实现createIteractor()

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

  

最后我们来看女Waitress如何运用这个迭代器的:

public void printVegetarianMenu() {
		Iterator iterator = allMenus.createIterator();

		System.out.println("\nVEGETARIAN MENU\n----");
		while (iterator.hasNext()) {
			MenuComponent menuComponent = 
					(MenuComponent)iterator.next();
			try {
				if (menuComponent.isVegetarian()) {
					menuComponent.print();
				}
			} catch (UnsupportedOperationException e) {}
		}
	}

 

  • 大小: 385.7 KB
  • 大小: 112.1 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics