`

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中封装了检索元素的方法。

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

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

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics