java 开发模式之十 : 迭代器模式

来源:互联网 发布:linux 下载命令 编辑:程序博客网 时间:2024/06/13 08:09

原理或定義

迭代器模式叫做游标(Cursor)模式。GOF给出的定义:提供一种方法访问一个容器(container)对象中的各个元素,而又不暴露该对象的内部细节

结构

迭代器角色(Iterator:负责定义访问和遍历元素的接口。
具体迭代器角色(Concrete Iterator:实现迭代器接口,并要记录遍历中的当前位置。
容器角色(Aggregate)负责提供创建具体迭代器角色的接口。
具体容器角色(ConcreteAggregate:实现创建具体迭代器角色的接口,这个具体迭代器角色与该容器的结构相

類圖

案例与代码

本模式使用两个菜馆合并后的菜单问题来作为案例

蛋糕店与餐厅合并后,怎么统一管理菜单项目
问题:一个用ArrayList管理菜单,一个用数组管理


一般设计方案:


通用菜单类:

public class MenuItem {private String name,description;private boolean vegetable;private float price;public MenuItem(String name,String description,boolean vegetable,float price){this.name=name;this.description=description;this.vegetable=vegetable;this.price=price;}public String getName(){return name;}public String getDescription(){return description;}public float getPrice(){return price;}public boolean  isVegetable(){return vegetable;}}

餐厅类:

public class CakeHouseMenu {private ArrayList<MenuItem> menuItems;public CakeHouseMenu() {menuItems = new ArrayList<MenuItem>();addItem("KFC Cake Breakfast","boiled eggs&toast&cabbage",true,3.99f);addItem("MDL Cake Breakfast","fried eggs&toast",false,3.59f);addItem("Stawberry Cake","fresh stawberry",true,3.29f);addItem("Regular Cake Breakfast","toast&sausage",true,2.59f);}private void addItem(String name, String description, boolean vegetable,float price) {MenuItem menuItem = new MenuItem(name, description, vegetable, price);menuItems.add(menuItem);}public ArrayList<MenuItem> getMenuItems() {return menuItems;}//其他功能代码}
public class DinerMenu {private final static int Max_Items=5;public int numberOfItems=0;private MenuItem[] menuItems;public DinerMenu(){menuItems=new MenuItem[Max_Items] ;addItem("vegetable Blt","bacon&lettuce&tomato&cabbage",true,3.58f);addItem("Blt","bacon&lettuce&tomato",false,3.00f);addItem("bean soup","bean&potato salad",true,3.28f);addItem("hotdog","onions&cheese&bread",false,3.05f);}private void addItem(String name, String description, boolean vegetable,float price) {MenuItem menuItem = new MenuItem(name, description, vegetable, price);if(numberOfItems>=Max_Items){System.err.println("sorry,menu is full!can not add another item");}else{menuItems[numberOfItems]=menuItem;numberOfItems++;}}public MenuItem[] getMenuItems() {return menuItems;}}


管理类 / 服务员类:

public class Waitress {private CakeHouseMenu mCakeHouseMenu;private DinerMenu mDinerMenu;private ArrayList<MenuItem> cakeitems;private MenuItem[] dineritems;public Waitress() {mCakeHouseMenu = new CakeHouseMenu();cakeitems = mCakeHouseMenu.getMenuItems();mDinerMenu = new DinerMenu();dineritems = mDinerMenu.getMenuItems();}public void printMenu() {MenuItem menuItem;for (int i = 0, len = cakeitems.size(); i < len; i++) {menuItem = cakeitems.get(i);System.out.println(menuItem.getName() + "***"+menuItem.getPrice()+"***"+ menuItem.getDescription());}for (int i = 0, len = mDinerMenu.numberOfItems; i < len; i++) {menuItem = dineritems[i];System.out.println(menuItem.getName() + "***"+menuItem.getPrice()+"***"+ menuItem.getDescription());}}public void printBreakfastMenu() {}public void printLunchMenu() {}public void printVegetableMenu() {}}

顾客 / 测试类:

public class MainTest {public static void main(String[] args) {Waitress mWaitress=new Waitress();//服务员展示2家餐厅合并的菜单mWaitress.printMenu();}}

此设计违法单一责任原则,当添加新餐厅,打印菜单的方法需要改变,而且复杂度和新餐厅的数据结构的复杂度成正比。


迭代器模式的设计方案:


通用菜单类不变。


迭代器角色(Iterator

public interface Iterator {public boolean hasNext();public Object next();}

餐厅类:

public class CakeHouseMenu {private ArrayList<MenuItem> menuItems;public CakeHouseMenu() {menuItems = new ArrayList<MenuItem>();addItem("KFC Cake Breakfast","boiled eggs&toast&cabbage",true,3.99f);addItem("MDL Cake Breakfast","fried eggs&toast",false,3.59f);addItem("Stawberry Cake","fresh stawberry",true,3.29f);addItem("Regular Cake Breakfast","toast&sausage",true,2.59f);}private void addItem(String name, String description, boolean vegetable,float price) {MenuItem menuItem = new MenuItem(name, description, vegetable, price);menuItems.add(menuItem);}public Iterator getIterator(){return new CakeHouseIterator() ;}class CakeHouseIterator implements  Iterator {private int position=0;public CakeHouseIterator(){  position=0;} @Overridepublic boolean hasNext() {// TODO Auto-generated method stubif(position<menuItems.size()){return true;}return false;}@Overridepublic Object next() {// TODO Auto-generated method stubMenuItem menuItem =menuItems.get(position);position++;return menuItem;}};//其他功能代码}

public class DinerMenu {private final static int Max_Items = 5;private int numberOfItems = 0;private MenuItem[] menuItems;public DinerMenu() {menuItems = new MenuItem[Max_Items];addItem("vegetable Blt", "bacon&lettuce&tomato&cabbage", true, 3.58f);addItem("Blt", "bacon&lettuce&tomato", false, 3.00f);addItem("bean soup", "bean&potato salad", true, 3.28f);addItem("hotdog", "onions&cheese&bread", false, 3.05f);}private void addItem(String name, String description, boolean vegetable,float price) {MenuItem menuItem = new MenuItem(name, description, vegetable, price);if (numberOfItems >= Max_Items) {System.err.println("sorry,menu is full!can not add another item");} else {menuItems[numberOfItems] = menuItem;numberOfItems++;}}public Iterator getIterator() {return new DinerIterator();}class DinerIterator implements Iterator {private int position;public DinerIterator() {position = 0;}@Overridepublic boolean hasNext() {// TODO Auto-generated method stubif (position < numberOfItems) {return true;}return false;}@Overridepublic Object next() {// TODO Auto-generated method stubMenuItem menuItem = menuItems[position];position++;return menuItem;}};}

服务员类:

public class Waitress {private ArrayList<Iterator> iterators=new ArrayList<Iterator>();public Waitress() {}public void addIterator(Iterator iterator){iterators.add(iterator);}public void printMenu() {Iterator iterator;MenuItem menuItem;for (int i = 0, len = iterators.size(); i < len; i++) {iterator = iterators.get(i);while(iterator.hasNext()){menuItem=(MenuItem)iterator.next();System.out.println(menuItem.getName() + "***"+menuItem.getPrice()+"***"+ menuItem.getDescription());}}}}

测试类:

public class MainTest {public static void main(String[] args) {Waitress mWaitress=new Waitress();CakeHouseMenu mCakeHouseMenu = new CakeHouseMenu();DinerMenumDinerMenu = new DinerMenu();mWaitress.addIterator(mCakeHouseMenu.getIterator());mWaitress.addIterator(mDinerMenu.getIterator());mWaitress.printMenu();}}


该案例可以直接使用JDK内置的迭代器接口作为迭代器角色:Iterator


迭代器模式:提供一种方法顺序访问一个聚合对象中的各个对象。



单一责任原则:一个类应该只有一个引起变化的原因.


使用場景

1. 访问一个聚合对象的内容而无需暴露它的内部表示

2.支持对聚合对象的多种遍历

3.为遍历不同的聚合结构提供一个统一的接口

 

優缺點

主要优点有:

1. 简化了遍历方式。

2.可以提供多种遍历方式,比如说对有序列表,我们可以根据需要提供正序遍历,倒序遍历两种迭代器。

3.封装性良好,用户只需要得到迭代器就可以遍历,而对于遍历算法则不用去关心

缺点主要有

对于比较简单的遍历(像数组或者有序列表),使用迭代器方式遍历较为繁琐,大家可能都有感觉,像ArrayList,我们宁可愿意使用for循环和get方法来遍历集合


迭代器模式是与集合共生共死的,一般来说,我们只要实现一个集合,就需要同时提供这个集合的迭代器,就像java中的CollectionListSetMap等,这些集合都有自己的迭代器。假如我们要实现一个这样的新的容器,当然也需要引入迭代器模式,给我们的容器实现一个迭代器

原创粉丝点击