迭代器模式——HeadFirst设计模式学习笔记
Posted HectorHou
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了迭代器模式——HeadFirst设计模式学习笔记相关的知识,希望对你有一定的参考价值。
迭代器模式:提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部表示
特点:
- 将客户端与对象集合的存储方式解耦,即客户遍历对象时无需知道对象的具体存储方式
- 封装变化的部分,即多个不同的集合的不同遍历方式,创建迭代器封装遍历每个对象集合的过程
- 客户不需要知道具体对象集合是如何存储的,也无需知道迭代器是如何实现的,只需通过迭代器进行遍历
- 封装了遍历
- 解决了依赖具体对象集合存储方式和依赖具体对象类型的问题
注意:
- 对于不支持remove方法的迭代器,可以抛出java.lang.UnsupportedOperationException
- 迭代器不意味着有次序
- 可以实现previous()方法向前调取对象
外部迭代器vs内部迭代器:
- 外部:客户通过next()调取下一个元素
- 内部:客户将具体操作传给迭代器,具体的调取由迭代器自己控制
单一责任原则:一个类应该只有一个变化的原因
- 将一个责任指派给一个类
- 类的每个责任都有改变的潜在区域,超过一个责任意味着超过一个改变区域
- 为了便于维护,设计单一责任的高内聚类(设计成完成一个或一组相关性高的功能)
举例:
餐厅对于早餐和午餐菜单的菜单项的底层存储方式不同,如果不进行任何优化,服务员遍历菜单时需要根据具体菜单的存储方式使用不同的遍历办法,也对于修改开放的方式不便于维护,不利于扩展
我们将变化的部分拿出来,创建具有单一责任的迭代器对象实现遍历菜单,并封装菜单的存储方式,使服务员无需知道,与服务员解耦
迭代器接口:
1 public interface Iterator { 2 boolean hasNext(); 3 Object next(); 4 }
晚餐菜单迭代器实现,针对其底层数组存储方式:
1 public class DinerMenuIterator implements Iterator { 2 MenuItem[] items; 3 int position = 0; 4 5 public DinerMenuIterator(MenuItem[] items) { 6 this.items = items; 7 } 8 9 public Object next() { 10 MenuItem menuItem = items[position]; 11 position = position + 1; 12 return menuItem; 13 } 14 15 public boolean hasNext() { 16 if (position >= items.length || items[position] == null) { 17 return false; 18 } else { 19 return true; 20 } 21 } 22 }
服务生通过迭代器遍历菜单:
1 public class Waitress { 2 Menu dinerMenu; 3 public Waitress( Menu dinerMenu) { 4 this.dinerMenu = dinerMenu; 5 } 6 public void printMenu() { 7 Iterator dinerIterator = dinerMenu.createIterator(); 8 9 System.out.println("/nLUNCH"); 10 printMenu(dinerIterator); 11 } 12 private void printMenu(Iterator iterator) { 13 while (iterator.hasNext()) { 14 MenuItem menuItem = (MenuItem)iterator.next(); 15 System.out.print(menuItem.getName() + ", "); 16 System.out.print(menuItem.getPrice() + " -- "); 17 System.out.println(menuItem.getDescription()); 18 } 19 }
以上是关于迭代器模式——HeadFirst设计模式学习笔记的主要内容,如果未能解决你的问题,请参考以下文章
Headfirst设计模式的C++实现——迭代器(Iterator)