设计模式(9)--迭代器与组合模式

来源:互联网 发布:网络常用端口号大全 编辑:程序博客网 时间:2024/04/26 17:51

(1)散列表(hashtable)         共迭代器获取 hashtable.values().iterator();  因为每一笔数据都是由键值对组成。

(2)迭代器是用来遍历集合的。 Java5后集合都出了自己的遍历方式 如增加for循环。           遍历 也称 游走。。。

(3)数组:Array 长定固定   集合:ArrayList 可扩展,取数据不需要转型 

(4)Java中有自己的迭代器接口。在java.util.Iterator  . 

(5)集合:collection 也可称为聚合(aggregate)。其存储方式可以是各种各样的数据结构,例如:列表 ,数组,散列表,

 (6)collection 中的  如 ArrayList.iterator() 方式即可实现迭代器   hashtable.value().iterator() 。 

(7)但数组不能通过 .iterator 的方式实现迭代器。 所以可以自定义迭代器。

单一责任:  设计原则: 一个类应该只有一个引起变化的原因 。如果一个类管理某种聚合,又负责遍历,则就有两种责任了。

内聚(cohesion):它用来度量一个类或模块紧密地达到单一目的或责任。

(1) 当一个模块或个类被设计成只支持一组相关的功能时,我们说它具有高内聚,返之,当被设计成支持一组不相关的功能时,我们说它具有低内聚。

(2)内聚是一个比单一责任原则更普遍的概念。两者关系密切。遵守这个原则的类容易具有高内聚。容易维护。

迭代器模式(Iterator Pattern):

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


例:现在有两个菜单,一个是数组,一个是ArrayList  。它俩的遍历方式不一样。 所以现在可以通过迭代器 封装遍历。

(-- 创建迭代器接口--)

(--创建一个菜单迭代器--) 此迭代器需要一个菜单数组做为参数

(--菜单中有一个createIteraor方法 返回一个菜单迭代器--)菜单中有菜单数组做为参数 给菜单迭代器。 然后利用菜单迭代器遍历菜单即可。

(--因为菜单中菜单数组做为参数 所以 Object next() 方法返回的是菜单中的菜单项--)

//定义迭代器接口public interface Iterator{  boolean hasNext();  Object next();}
//实现一个具体的迭代器 (数组菜单的)public class DinerMenuIterator implements Iterator{ //实现迭代器接口
    MenuItem[] items ;
    int position =0;  //当前数组遍历的位置
    public DinerMenuIterator(MenuItem[] items){
       this.items = items;   //传入一个菜单项的数组当做参数
    }    public Object next(){
       MenuItem menuItem = items[position];
       position = position+1;
       return menuItem;  
    }
    public boolean hasNext(){
       if(position>=items.length || items[position]==null){
          return false;
       }else{
          return true;          //hasNext()方法会检查我们是否已经取得数组的所有的元素。如果还有元素待遍历。,则返回true.
       }
    }}
<pre name="code" class="java">// 利用迭代器改写菜单public class DinerMenu{  static final int MAX_ITEMS = 6;  //菜单中有6个菜
  int numberOfItems = 0;
  MenuItem[] menuitems;           //菜单项 组成的数组
  //构造器
  //addItem()
  public Iterator createIterator(){
    reuturn new DinerMenuIterator(menuItems);   返回一个菜单迭代器
  //返回迭代器接口。客户不知道 菜单是如何维护菜单项的,也不需要知道迭代器是如何迭现的。只需要利用这个迭代器遍历菜单即可。}
</pre><pre name="code" class="java">  //利用迭代器遍历菜单
  private void printMenu(Iterator iterator){     //菜单创建出来的菜单迭代器 <span style="color:#ff0000;">会引用菜单中的菜单数组作为参数</span>
    while(iterator.hasNext()){
   <span style="white-space:pre"></span> MenuItem menuItem = (MenuItem)iterator.next();
    }
  }
//数组菜单 的createIterator()方法 返回一个自定义的 菜单迭代器
//<span style="color:#ff0000;">Arraylist 的菜单 createItertor()方法 可以直接 调用 .iterator()方法返回 一个菜单迭代器</span>。 

上面是自定义迭代器。 可以使用java中的迭代器 java.util.Iterator 接口。
interface Iterator{
 hasNext()
 next()
 remove()  //
}
如果不提供 remove() 功能 则可以抛出运行时异常 。java.lang.UnsupportedOperationException。

ArrayList 有一个返回代器的iterator()方法  。ArrayList 并不需要实现自忆的迭代器
</pre><pre name="code" class="java">问: 在多线程下,可能会有多个迭代器引用同一个对象聚合。 remove()会造成怎样的影响?
答: 后果并没有指明 。当多线程使用迭代器时,必须特别小心。

迭代器模式让我们能游走于聚合内的每一人元素,而又不暴露其内部的表示

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

Java中有一个Enumeration(枚举)接口,  java.util.Enumeration 是一个有序的迭代器实现。 

它有两个方法: hasMoreElements() 和 nextElement()。

你应该比较想用迭代器,而不是枚举。因为大多数的java类支持迭代器。

如果想把两者互想转换。 可以用适配器。。。


0 0