java设计模式-----19、迭代模式
概念:
Iterator模式也叫迭代模式,是行为模式之一,它把对容器中包含的内部对象的访问委让给外部类,使用Iterator(遍历)按顺序进行遍历访问的设计模式。
迭代模式使用比较少,JDK集合也提供了Iterator的具体实现,可以直接拿来用,不必自己实现
在应用Iterator模式之前,首先应该明白Iterator模式用来解决什么问题。或者说,如果不使用Iterator模式,会存在什么问题。
1.由容器自己实现顺序遍历。直接在容器类里直接添加顺序遍历方法
2.让调用者自己实现遍历。直接暴露数据细节给外部
我们用代码实现一下
首先,新建一个Book类,这是容器中的内容
1 public class Book { 2 private String id; 3 private String name; 4 private double price; 5 6 public Book(String id, String name, double price) { 7 this.id = id; 8 this.name = name; 9 this.price = price; 10 } 11 12 public String getId() { 13 return id; 14 } 15 16 public void setId(String id) { 17 this.id = id; 18 } 19 20 public String getName() { 21 return name; 22 } 23 24 public void setName(String name) { 25 this.name = name; 26 } 27 28 public double getPrice() { 29 return price; 30 } 31 32 public void setPrice(double price) { 33 this.price = price; 34 } 35 36 public void display() { 37 System.out.println("ID=" + id + ",\tname=" + name + ",\tprice" + price); 38 } 39 }
再新建一个容器
1 public class BookList { 2 //容器内部还是一个List,也可以用数组 3 private List<Book> bookList = new ArrayList<Book>(); 4 private int index; 5 6 //添加书籍 7 public void addBook(Book book){ 8 bookList.add(book); 9 } 10 11 //删除书籍 12 public void removeBook(Book book){ 13 int bookIndex = bookList.indexOf(book); 14 bookList.remove(bookIndex); 15 } 16 17 //判断是否有下一本书 18 public boolean hasNext(){ 19 if(index >= bookList.size()){ 20 return false; 21 } 22 return true; 23 } 24 25 //获得下一本书 26 public Book getNext(){ 27 return bookList.get(index++); 28 } 29 30 //获取集合长度 31 public int getSize(){ 32 return bookList.size(); 33 } 34 35 //根据index获取Book 36 public Book getByIndex(int index){ 37 return bookList.get(index); 38 } 39 }
接下来,就是迭代容器了,先采用第一种方式(由容器自己实现顺序遍历。直接在容器类里直接添加顺序遍历方法)
public class MainClass { public static void main(String[] args) { BookList bookList = new BookList(); Book book1 = new Book("001","设计模式",200); Book book2 = new Book("002","Java核心编程",200); Book book3 = new Book("003","计算机组成原理",200); bookList.addBook(book1); bookList.addBook(book2); bookList.addBook(book3); while(bookList.hasNext()){ Book book = bookList.getNext(); book.display(); } } }
结果如下:
然后是第二种方式(让调用者自己实现遍历。直接暴露数据细节给外部)
1 public class MainClass { 2 public static void main(String[] args) { 3 BookList bookList = new BookList(); 4 5 Book book1 = new Book("001","设计模式",200); 6 Book book2 = new Book("002","Java核心编程",200); 7 Book book3 = new Book("003","计算机组成原理",200); 8 9 bookList.addBook(book1); 10 bookList.addBook(book2); 11 bookList.addBook(book3); 12 13 for(int i = 0; i < bookList.getSize(); i++){ 14 Book book = bookList.getByIndex(i); 15 book.display(); 16 } 17 } 18 }
结果同上
但这样,一定是有缺点的,不然就没有必要使用迭代模式了
不使用迭代模式的缺点
以上方法1与方法2都可以实现对遍历,但有这些问题
1,容器类承担了太多功能:一方面需要提供添加删除等本身应有的功能;一方面还需要提供遍历访问功能。
2,往往容器在实现遍历的过程中,需要保存遍历状态,当跟元素的添加删除等功能夹杂在一起,很容易引起混乱和程序运行错误等。
应用迭代模式的条件
Iterator模式就是为了有效地处理按顺序进行遍历访问的一种设计模式,简单地说,Iterator模式提供一种有效的方法,可以屏蔽聚集对象集合的容器类的实现细节,而能对容器内包含的对象元素按顺序进行有效的遍历访问。
所以,Iterator模式的应用场景可以归纳为满足以下几个条件:
1、访问容器中包含的内部对象
2、按顺序访问
迭代模式的结构
迭代模式的角色和职责
1、Iterator(迭代器接口):
该接口必须定义实现迭代功能的最小定义方法集
比如提供hasNext()和next()方法。
2、ConcreteIterator(迭代器实现类):
迭代器接口Iterator的实现类。可以根据具体情况加以实现。
3、Aggregate(容器接口):
定义基本功能以及提供类似Iterator iterator()的方法。
4、concreteAggregate(容器实现类):
容器接口的实现类。必须实现Iterator iterator()方法。
接下来,用代码实现一下迭代模式,只需修改BookList即可
1 public class BookList { 2 //容器内部还是一个List,也可以用数组 3 private List<Book> bookList = new ArrayList<Book>(); 4 private int index; 5 6 //添加书籍 7 public void addBook(Book book){ 8 bookList.add(book); 9 } 10 11 //删除书籍 12 public void removeBook(Book book){ 13 int bookIndex = bookList.indexOf(book); 14 bookList.remove(bookIndex); 15 } 16 17 //判断是否有下一本书 18 // public boolean hasNext(){ 19 // if(index >= bookList.size()){ 20 // return false; 21 // } 22 // return true; 23 // } 24 25 //获得下一本书 26 // public Book getNext(){ 27 // return bookList.get(index++); 28 // } 29 30 //获取集合长度 31 public int getSize(){ 32 return bookList.size(); 33 } 34 35 //根据index获取Book 36 public Book getByIndex(int index){ 37 return bookList.get(index); 38 } 39 40 //得到Iterator实例 41 public Iterator Iterator() { 42 return new Itr(); 43 } 44 45 //内部类,Iterator实例(因为要使用容器的内部信息,所以要写成内部类) 46 private class Itr implements Iterator{ 47 //判断是否有下一本书,将刚才hasNext()中内容复制过来即可 48 public boolean hasNext() { 49 if(index >= bookList.size()){ 50 return false; 51 } 52 return true; 53 } 54 //获得下一本书,将刚才getNext()中内容复制过来即可 55 public Object next() { 56 return bookList.get(index++); 57 } 58 59 public void remove() { 60 61 } 62 } 63 }
再在客户端实现一下
1 public class MainClass { 2 public static void main(String[] args) { 3 BookList bookList = new BookList(); 4 5 Book book1 = new Book("001","设计模式",200); 6 Book book2 = new Book("002","Java核心编程",200); 7 Book book3 = new Book("003","计算机组成原理",200); 8 9 bookList.addBook(book1); 10 bookList.addBook(book2); 11 bookList.addBook(book3); 12 13 Iterator iterator = bookList.Iterator(); 14 while(iterator.hasNext()){ 15 Book book = (Book) iterator.next(); 16 book.display(); 17 } 18 } 19 }
可以看到,这和使用JDK提供集合的Iterator方法就一模一样了。
迭代模式的优缺点
优点:
1,实现功能分离,简化容器接口。让容器只实现本身的基本功能,把迭代功能委让给外部类实现,符合类的设计原则。
2,隐藏容器的实现细节。
3,为容器或其子容器提供了一个统一接口,一方面方便调用;另一方面使得调用者不必关注迭代器的实现细节。
4,可以为容器或其子容器实现不同的迭代方法或多个迭代方法。
缺点:
由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。