迭代器模式Iterator
2018-03-23 14:18
155 查看
迭代器用途:遍历每一个含有的元素
例如,数组遍历
例如,链表遍历
例如,键值对遍历
测试结果
由上导致的问题
必须要了解所遍历的对象数据结构,不然无法得知如何遍历
在编写遍历时候,各种数据结构代码都不一样,不能复用
食品项
早餐店的服务员展示菜单
测试
测试结果
服务员代码
测试代码
测试结果
服务员现在要清楚两个不同模型的遍历了,但是原服务员只知道一家的数据结构,最好的办法是屏蔽到数据结构细节,只需要遍历就行了(迭代器思想)
对应步骤:
定义通用访问接口Iterator
将BreakfastMenu通过BreakfastMenuIterator适配器转换接口为Iterator
将LunchMenu通过LunchMenuIterator适配器转换接口为Iterator
Waitress只访问Iterator,目的是与具体的数据结构解耦
对应修改代码
新增接口
新增适配器
一个服务员
测试代码
测试结果
达到预期结果
橘黄色为我们平时使用的集合
对应修改代码
测试代码
主要讲解for/in语句
主要思想为迭代器
为什么需要迭代器
由于数据结构导致了不同结构数据不一致,相应的操作也有差异例如,数组遍历
int[] ints = {1, 2, 3}; if (ints != null) { for (int i = 0; i < ints.length; i++) { System.out.println(ints[i]); } }
例如,链表遍历
List<String> lists = new ArrayList<>(); lists.add("a"); lists.add("b"); lists.add("c"); if (lists != null) { for (int i = 0; i < lists.size(); i++) { String temp = lists.get(i); System.out.println(temp); } }
例如,键值对遍历
Map<String, String> map = new HashMap<>(); map.put("a", "A"); map.put("b", "B"); map.put("c", "C"); if (map != null) { //键稽核 Set<String> sets = map.keySet(); //这里使用for循环方式不合适,因为数组与List都可以使用这个,主要是没有其他合适方法输出Set集合 for (String key : sets) { String value = map.get(key); System.out.println("key: " + key + ", value:" + value); } }
测试结果
1 2 3 a b c key: a, value:A key: b, value:B key: c, value:C
由上导致的问题
必须要了解所遍历的对象数据结构,不然无法得知如何遍历
在编写遍历时候,各种数据结构代码都不一样,不能复用
解决方法,抽象一层遍历接口
具体的例子演进
当前开了两家吃饭的店,一家卖早餐,一家卖午餐,他们都有自己的菜单和服务员食品项
package headfirst.hd.iterator.eg2; public class Item { private String name; private float price; public Item(String name, float price) { this.name = name; this.price = price; } @Override public String toString() { return "[商品名=" + name + ", 价格=" + price + "]"; } }
早餐店的菜单,采用数组结构存储
package headfirst.hd.iterator.eg2; //早餐店品种较少,且种类变化不大,用数组实现 public class BreakfastMenu { static final int MAX = 5; // 使用数组形式 private Item[] items; int index = 0; public BreakfastMenu() { items = new Item[MAX]; addItem("包子", 1.5f); addItem("豆浆", 2.00f); addItem("油条", 0.99f); addItem("大饼", 2.5f); addItem("小笼包", 1f); } public void addItem(String name, float price) { Item item = new Item(name, price); if (index >= MAX) { System.err.println("菜单已经满了,不能添加新种类了"); } else { items[index] = item; index = index + 1; } } public Item[] getMenuItems() { return items; } }
早餐店的服务员展示菜单
package headfirst.hd.iterator.eg2; public class WaitressBreakfast { private BreakfastMenu menu; public WaitressBreakfast(BreakfastMenu menu) { this.menu = menu; } public void printMenus() { Item[] menuItems = menu.getMenuItems(); //进行遍历 for (int i = 0; i < menuItems.length; i++) { Item item = menuItems[i]; System.out.println(item); } } }
测试
package headfirst.hd.iterator.eg2; public class Client { public static void main(String[] args) { BreakfastMenu breakfastMenu = new BreakfastMenu(); WaitressBreakfast breakfast = new WaitressBreakfast(breakfastMenu); breakfast.printMenus(); } }
测试结果
[商品名=包子, 价格=1.5] [商品名=豆浆, 价格=2.0] [商品名=油条, 价格=0.99] [商品名=大饼, 价格=2.5] [商品名=小笼包 106a6 , 价格=1.0]
午餐店的菜单,采用链表结构存储
package headfirst.hd.iterator.eg2; import java.util.ArrayList; import java.util.List; //午餐品种较多,经常添加新品种,用List数据结构 public class LunchMenu { private List<Item> items = new ArrayList<>(); public LunchMenu() { addItem("鸡", 15f); addItem("鸭", 20f); addItem("牛", 29f); addItem("羊", 25f); addItem("蛋炒", 10f); addItem("笋", 12f); addItem("其他1", 13f); addItem("其他2", 15f); addItem("其他3", 18f); } public void addItem(String name, float price) { Item item = new Item(name, price); items.add(item); } public List<Item> getMenuItems() { return items; } }
服务员代码
package headfirst.hd.iterator.eg2; import java.util.List; public class WaitressLauch { private LunchMenu menu; public WaitressLauch(LunchMenu menu) { this.menu = menu; } public void printMenus() { List<Item> menuItems = menu.getMenuItems(); //进行遍历 for (int i = 0; i < menuItems.size(); i++) { Item item = menuItems.get(i); System.out.println(item); } } }
测试代码
package headfirst.hd.iterator.eg2; public class Client { public static void main(String[] args) { LunchMenu lunchMenu = new LunchMenu(); WaitressLauch lauch = new WaitressLauch(lunchMenu); lauch.printMenus(); } }
测试结果
[商品名=鸡, 价格=15.0] [商品名=鸭, 价格=20.0] [商品名=牛, 价格=29.0] [商品名=羊, 价格=25.0] [商品名=蛋炒, 价格=10.0] [商品名=笋, 价格=12.0] [商品名=其他1, 价格=13.0] [商品名=其他2, 价格=15.0] [商品名=其他3, 价格=18.0]
早餐店和午餐店合并了
问题:只需要一个服务员,但是早餐店的服务员只知道数据结构的实现,午餐店的服务员只知道链表结构的实现,现在又只想雇佣其中一家的服务员,但是又不想修改原有的数据结构先关的代码原两家店模型设计
合并后模型-错误
服务员现在要清楚两个不同模型的遍历了,但是原服务员只知道一家的数据结构,最好的办法是屏蔽到数据结构细节,只需要遍历就行了(迭代器思想)
修改模型设计,引入适配器模式达到迭代目标
适配器模式入门:https://blog.csdn.net/dengjili/article/details/79485034对应步骤:
定义通用访问接口Iterator
将BreakfastMenu通过BreakfastMenuIterator适配器转换接口为Iterator
将LunchMenu通过LunchMenuIterator适配器转换接口为Iterator
Waitress只访问Iterator,目的是与具体的数据结构解耦
对应修改代码
新增接口
package headfirst.hd.iterator.eg2; public interface Iterator<T> { T next(); boolean hasNext(); }
新增适配器
package headfirst.hd.iterator.eg2; //转换数据结构 public class BreakfastMenuIterator implements Iterator<Item> { private Item[] items; private int index = 0; public BreakfastMenuIterator(Item[] items) { this.items = items; } @Override public Item next() { Item item = items[index]; index = index + 1; return item; } @Override public boolean hasNext() { //传入空对象 if (items == null) { return false; } //读取到数组尾部 if (index >= items.length) { return false; } //没初始化对应的值 if (items[index] ==null) { return false; } return true; } }
package headfirst.hd.iterator.eg2; import java.util.List; //转换数据结构 public class LunchMenuIterator implements Iterator<Item>{ private List<Item> items; private int index = 0; public LunchMenuIterator(List<Item> items) { this.items = items; } @Override public Item next() { Item item = items.get(index); index = index + 1; return item; } @Override public boolean hasNext() { //传入空对象 if (items == null) { return false; } //读取到数组尾部 if (index >= items.size()) { return false; } //没初始化对应的值 if (items.get(index) ==null) { return false; } return true; } }
一个服务员
package headfirst.hd.iterator.eg2; public class Waitress { //不清楚是哪一种数据结构 public void printMenus(Iterator<? extends Item> iterator) { //进行遍历 while (iterator.hasNext()) { Item item = iterator.next(); System.out.println(item); } } }
测试代码
package headfirst.hd.iterator.eg2; public class Client { public static void main(String[] args) { //两份菜单,通过这种方式可以是任意多菜单和任意数据结构 BreakfastMenu breakfastMenu = new BreakfastMenu(); LunchMenu lunchMenu = new LunchMenu(); //一个服务员 Waitress waitress = new Waitress(); System.out.println("打印早餐:"); //通过适配器 waitress.printMenus(new BreakfastMenuIterator(breakfastMenu.getMenuItems())); System.out.println("打印午餐:"); //通过适配器 waitress.printMenus(new LunchMenuIterator(lunchMenu.getMenuItems())); } }
测试结果
打印早餐:
[商品名=包子, 价格=1.5]
[商品名=豆浆, 价格=2.0]
[商品名=油条, 价格=0.99]
[商品名=大饼, 价格=2.5]
[商品名=小笼包, 价格=1.0]
打印午餐:
[商品名=鸡, 价格=15.0] [商品名=鸭, 价格=20.0] [商品名=牛, 价格=29.0] [商品名=羊, 价格=25.0] [商品名=蛋炒, 价格=10.0] [商品名=笋, 价格=12.0] [商品名=其他1, 价格=13.0] [商品名=其他2, 价格=15.0] [商品名=其他3, 价格=18.0]
达到预期结果
完善模型设计,达到最终迭代器模式
橘黄色为我们平时使用的集合
对应修改代码
package headfirst.hd.iterator.eg2; //早餐店品种较少,且种类变化不大,用数组实现 public class BreakfastMenu { static final int MAX = 5; // 使用数组形式 private Item[] items; int index = 0; public BreakfastMenu() { items = new Item[MAX]; addItem("包子", 1.5f); addItem("豆浆", 2.00f); addItem("油条", 0.99f); addItem("大饼", 2.5f); addItem("小笼包", 1f); } public void addItem(String name, float price) { Item item = new Item(name, price); if (index >= MAX) { System.err.println("菜单已经满了,不能添加新种类了"); } else { items[index] = item; index = index + 1; } } public Iterator<Item> createIterator() { return new BreakfastMenuIterator(items); } }
package headfirst.hd.iterator.eg2; import java.util.ArrayList; import java.util.List; //午餐品种较多,经常添加新品种,用List数据结构 public class LunchMenu { private List<Item> items = new ArrayList<>(); public LunchMenu() { addItem("鸡", 15f); addItem("鸭", 20f); addItem("牛", 29f); addItem("羊", 25f); addItem("蛋炒", 10f); addItem("笋", 12f); addItem("其他1", 13f); addItem("其他2", 15f); addItem("其他3", 18f); } public void addItem(String name, float price) { Item item = new Item(name, price); items.add(item); } public Iterator<Item> createIterator() { return new LunchMenuIterator(items); } }
测试代码
package headfirst.hd.iterator.eg2; public class Client { public static void main(String[] args) { //两份菜单,相当于我们平时用的集合 BreakfastMenu breakfastMenu = new BreakfastMenu(); LunchMenu lunchMenu = new LunchMenu(); //一个服务员 Waitress waitress = new Waitress(); System.out.println("打印早餐:"); //通过适配器 waitress.printMenus(breakfastMenu.createIterator()); System.out.println("打印午餐:"); //通过适配器 waitress.printMenus(lunchMenu.createIterator()); //上述代码像我们平时用的代码 //List<Item> list = new ArrayList<>(); //list.iterator(); } }
java的迭代器和集合
java也有一个Iterator接口,和我们上面例子一致,这里不多讲主要讲解for/in语句
int[] ints = {1, 2, 3}; for (int i : ints) { System.out.println(i); } List<String> lists = new ArrayList<>(); lists.add("a"); lists.add("b"); lists.add("c"); for (String s : lists) { System.out.println(s); } Map<String, String> map = new HashMap<>(); map.put("a", "A"); map.put("b", "B"); map.put("c", "C"); if (map != null) { //键稽核 Set<String> sets = map.keySet(); //这里使用for循环方式不合适,因为数组与List都可以使用这个,主要是没有其他合适方法输出Set集合 for (String key : sets) { String value = map.get(key); System.out.println("key: " + key + ", value:" + value); } }
主要思想为迭代器
多个Iterator的整合应用
对应链接:https://blog.csdn.net/dengjili/article/details/79720730相关文章推荐
- java设计模式-迭代器模式(Iterator)
- 迭代器模式(Iterator Pattern)
- 设计模式—Iterator迭代器模式
- 迭代器模式iterator pattern
- (第Ⅳ部分 行为型模式篇) 第17章 迭代器模式(Iterator Pattern)
- 步步为营 .NET 设计模式学习笔记 十一、Iterator(迭代器模式)
- c++设计模式之Iterator迭代器模式.txt
- 极速理解设计模式系列:16.迭代器模式(Iterator Pattern)
- 迭代器模式(Iterator)
- 设计模式(十六)----- 迭代器模式(Iterator)----(JAVA版)
- 迭代器模式(Iterator)
- 迭代器模式 The Iterator Pattern
- Iterator 迭代器模式 笔记
- 【Unity与23种设计模式】迭代器模式(Iterator)
- 迭代器模式(Iterator Pattern)
- 24.迭代器模式--Iterator
- 设计模式之迭代器模式(Iterator Pattern)
- Iterator Pattern 迭代器模式
- 23设计模式之迭代器模式(Iterator)
- 设计模式 --迭代器模式(Iterator)