5-Iterators: decoupling algorithms from containers

In the process, he realized that iterators are central to the use of algorithms, because they decouple the algorithms from the specific type of containe...只看这个,不是很好理解。

找了两个资料,感觉是比较好的例子:

<1>

Iterator模式的疑问

http://www.jdon.com/jivejdon/thread/34664

 

JAVA COLLECTION类都提供Iterator模式来迭代的取数据,比如ArrayList最终实现Iterable接口,但是
(一)
for(int i=0,i<size;i++){
a.get(i);
......
}

(二)
Iterator i = a.inerator();
while(i.hasNext()){
......
}

1和2都能遍历list实例a的所有元素,没看出用iterator有什么优势。

起先我的想法就是Iterator提供了List的一个不可变视图,如果你想把List发布给一个方法查看而又不希望这个方法能修改它,则发给给该方法一个List的不可更改视图,但是这个想法有几个问题:
(1)Iterator并非不可改,有remove方法
(2)如果是发布不可变试图的话完全可以用Collections.unmodifyList(a);
(3)如果仅仅是发布不可变视图的话也未必要是Iterator这个形式,试想一下,一个方法的参数是Iterator将是多么晦涩难理解的,我也没见过这个用的。

我的第二个想法是Iterable接口是所有Collection对象都必实现的,也许在List里体现不出优势,在其他集合类里能体现出来,List实现Iterable只是List作为集合类所顺理成章实现的。

到底Iterator的优势在哪里

 

其中一个评论比较有总结性,这应该就是面向接口编程+遵守规范的优越性!

 

为什么使用iterator,就是因为用***.iterator 来隐藏***的内部实现。

 

<2>

Iterator模式的几种用法:

http://www.jdon.com/jivejdon/thread/32038

Iterator模式的几种用法

在网络上看帖子时发现不少模式的初学者对Iterator模式的理解仅仅停留在从类库的容器类取得Iterator来遍历容器中的内容的程度。

因此在这里写几个例子,来加深大家对Iterator模式的理解。

 

对容器中元素的访问涉及到3个方面。

1.容器的类型

2.检索容器内元素的方法

3.对元素的操作

比如说我们有一个表示书店的book_store类。里面保存了各种各样的book类的实例。

book类有name和type两种属性。表示书的名字和类别。

因此book_store类内部会用一个容器来保存book的实例。比如list。

class book

{

public:

string name;

string type;

};

 

class book_store

{

private:

list<book> m_books;

};

 

我们现在有这样一个简单的应用,那就是输出所有的书名到屏幕。

那么我们来看一下在引入Iterator模式前有那几种实现方法,各有什么缺点。

1.给book_store类增加一个print_book_name的函数。来实现这个功能。

这样做的缺点有两个:

(1).将输入输出逻辑和业务对象绑定在一起,导致了今后系统难以变更。

(2).输出逻辑和内部实现绑定。

比如现在要把输出到屏幕改成输出到log文件的话,那么就需要修改print_book_name了。

2.给book_store类增加一个get_list函数。然后写一个print_book类来负责打印书名的列表。这是一个初学者常用的方式。表面上看来似乎两个类各担其责,一个表示业务对象一个负责打印。

如果需要打印到log文件的话,只要新增加一个log_book类,book_store和print_book都不受影响。解决了上面的这个问题。

这样做的缺点是:

(1).把book_store类的内部实现给暴露出来了,违反了封装的原则。

如果现在把内部容器类型从list换成了vector的话,就要修改输出逻辑了。也就是说,要同时改写print_book类和log_book类。

3.增加一个list和vector类共同的基类/接口,比如I_container。然后给book_store类增加一个get_books函数,返回I_container。

这在一定程度上解决了上面的问题。但是并不彻底。应为还是暴露了内部的实现,只不过从list上升到了I_container。

· 如果现在系统发生了变化,book_store不再在本地保存books了,而是需要通过网络取得的话,print_book和log_book就无法对应了。

· 另一个限制是,我需要一个新的机能,那就是打印所有type为”烹饪书”的机能的话,就需要一个print_cook_book类了,而这里边的格式化代码和输出代码和print_book是相同的。重复代码是维护的噩梦。

 

接下来我们看一下Iterator模式如何解决以上的这些问题。

首先,我们引入一个I_iterator的Interface。

然后创建一个I_iterator的实现类all_book_iterator。这个类可以迭代book_store中的所有book。

接下来创建一个print_book类,从I_iterator中取得每一个book,然后打印到屏幕。

 

下面我们看一下如何对应上面的这些需求变更。

1.要求输出到log文件

追加一个log_book类,其他都类都不需要改变。

2.将内部容器从list变成vector。

修改iterator中的相关代码。Iterator的使用者不会受到影响。

3.从网络取得数据。

修改iterator中的相关代码。Iterator的使用者不会受到影响。

4.按照type检索

在iterator中添加一个type的属性,或者是构造一个新的type_search_iterator。

在iterator中把不符合检索条件的book过滤掉。

5.按照某一特定顺序输出book名到屏幕,或是log文件。

实现一个按该顺序输出的iterator。

6.以同样的方式打印cd_store。

实现对应于cd_store的iterator。

 

可见,iterator模式在各种iterator中封装了检索元素的方法。

将容器和对容器中元素的操作完全隔开。

大大增加了代码的可重用性。

你可能感兴趣的:(设计模式,迭代器,Iterators)