缓存(caching): 当组合结构很复杂,或者遍历的代价太高,那么实现组合节点的缓存就很有帮助。
(1) Java Collection Framework 指的是一群类的接口。 其中包括了 ArrayList, Vector , LinkedList , Stack ,和 PriorityQueue. 这些类都实现了java.util.Collection接口。
(2) Collection接口中的一些方法:
add() , addAll() , clear() , contains() , containsAll() , equals() , hashCode() , isEmpty() ,
iterator() , remove() , removeAll() , retainAll()--交集 size() , toArray()
(3)Java5 的迭代器和集合 。 新形式的for语句 , 称为for / in 这可以让你在一个集合或者一个数组中遍历,而且不需要显示创建迭代器。
(4)需要使用Java 5 的泛型(generic)特性来确保for / in 的类型安全。
组合模式 : 就是树形结构 有 子节点和叶节点 子节点下还可以有子节点和叶节点。 (一般使用递归遍历)
如菜单中还可以有子菜单
组合模式: 允许你将对象组合成树形结构来表现“整体/部分” 层次结构 ,组合能让客户以一致的方式处理个别对象以及对象组合。
(1) 组合模式让我们能用树形方式创建对象的结构,树里面包含了组合以及个别的对象。
(2)使用组合结构,我们能把相同的操作应用在组合和个别对象上。换句话说,在大多数情况下,我们可以忽略对象组合和个别对象的差别。
一个菜单中还有子菜单 子菜单是以组合的方式
例:
MenuComponent类是 抽象的 组件基类 (菜单项 或子菜单 )
public class Menu extends MenuComponent{
ArrayList menuComponents = new ArrayList();
String name;
String description;
//构造器
public void print(){
syso.name;
syso.description;
Iterator iterator = menuComponents.iterator(); //如果菜单中碰见子菜单。
while(iterator.hasNext()){
MenuComponent menuComponent = (MenuComponent)iterator.next();
menuComponent.print();
//递归。
}
}
}
组件:分为组合(子菜单) 。叶节点(菜单项)。
如:一个菜单如下:
红烧排骨
黄焖鸡
龙虾
子菜单 。。。。
大龙虾
组合模式以单一责任设计原则换取透明性(transparency).什么是透明性?通过让组件的接口同时包含一些管理了节点和叶节点的操作,客户就可以将组合和叶节点一视同仁。
例2:
public class Menu extends MenuComponent{ //子菜单
public Iterator createIterator(){
return new CompositeIterator(menuComponents.iterator()); //子菜单的迭代器。
}
}
public class MenuItem extends MenuComponent{ //菜单项
public Iterator createIterator(){
return new NullIterator(); //空的迭代器。 因为菜单项不需要迭代
}
}
CompositeIterator 确保 所有的子菜单(。。子子菜单)迭代器 都被包括进来。
public class CompositeIterator implements Iterator{ //和所有迭代器一样实现Iterator接口。
Statck 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()); //如果元素是子菜单,则把子菜单迭代器放入stack中。 等待遍历。
}
return component; //不管是 菜单项 还是子菜单 都返回。 打印出来
}else{
return null;
}
}
public boolean hasNext(){
if(stack.empty()){
return false;
}else{
Iterator iterator = (Iterator) stack.peek(); //取出顶层迭代器。
if( ! iterator.hasNext()){ //查看它是否有下一个元素如果没有(则是NullIterator 也就是菜单项 )弹出值栈,并移除。
stack.pop(); //返回并从堆栈中移除
return hasNext(); //递归调用 hasNext();
}else{
return true;
}
}
}
public void remove(){
throw new UnsupportedOperationException(); //不支持删除。这里只有遍历。
}
}
在我们在例1中写 递当print()时。 我们利用一个迭代器来遍历组件内的每个项。如果遇到的是菜单,(而不是菜单项),我们就会递归地调用print()方法处理它。换句话说,
其是在“ 内部 ” 自行处理遍历。
但例2 则是“ 外部 “的迭代器。这个例子中,必须维护组合递归结构的位置,也就是为什么在组合层次结构中上上下下时,使用堆栈来维护我们的位置。
==== 为了要保持透明性,组合内所有的对象必须实现相同的接口(如:子菜单和菜单项)
空迭代器
public class NullIterator implements Iterator{
public Object next(){
return null;
}
pubic boolean hasNext(){
return false; //永远返回 false;
}
public void remove(){
throw new UnsupportedOperationException();
}
}
要点:
(1)迭代器允许访问聚合的元素,而不需要暴露它的内部结构
(2)迭代器将遍历聚合的工作封装进一个对象中
(3)当使用迭代器的时候,我们依赖聚合提供遍历
(4)迭代器提供了一个通用的接口,让我们遍历聚合的项,当我们编码使用聚合的项时,就可以使用多态机制。 (子菜单和菜单项 多态为菜单)
(5)我们应该努力让一个类只分配一个责任
(6)组合模式提供一个结构,可同时包容个别对象以及组合对象一视同仁 (子菜单 和菜单项)
(7)组合结构内的任意对象称为组件,组件可以是组合,也可以是叶节点。
(8)在实现组合模式时,有许多设计上的折衷。你要根据需要平衡透明性和安全性。
设计模式(9.1)--迭代器与组合模式,布布扣,bubuko.com