迭代器是这么个东西:
- interface Iterator
- {
- virtual bool hasNext() = 0;
- virtual Object* next() = 0;
- };
它用于遍历一个集合。这个集合的内部实现可以是数组、链表甚至是哈希表,但外部根本不需要知道,只要这个集合提供出一个得到Iterator的方法:
- class Collection
- {
- public:
- Iterator createIterator();
- };
这样客户就可以简单地遍历这个集合:
- class Client
- {
- void DoSomething(Collection* pCollection)
- {
- Iterator itor = pCollection->createIterator();
- while(itor.hasNext())
- Object* pObj = itor.next();
- }
- };
设计原则:一个类应该只有一个引起变化的原因。
把遍历从集合本身独立出来就是为了分离变化,这样集合本身职责就更加单一,它不需要承担遍历方法改变的风险。比如要支持逆向遍历时,只要添加或改变iterator,而集合本身并不用太大改变。
当一个集合是一个层次结构,比如是一棵树时,简单的迭代器就有点捉襟见肘了。如何把这样的层次结构封装得好呢?怎样对外部隐藏实现细节,但又能够表示出这种层次结构?
定义一个接口Component:
- interface Component
- {
- virtual void add(Component*) = 0;
- virtual void remove(Component*) = 0;
- virtual Component* getChild(int) = 0;
- };
集合中所有的结点都实现这个接口。每个结点可以是两种类型:Leaf或Composite
- class Leaf : public Component
- {
- // doesn't support add/remove/getChild
- };
- class Composite : public Component
- {
- public:
- virtual void add(Component*);
- virtual void remove(Component*);
- virtual Component* getChild(int);
- };
组合模式允许你将对象组合成树形结构来表现“整体/部分”层次结构。组合能让客户以一致的方式处理个别对象以及对象组合。
有了组合模式后,Component就可以提供适合于它的iterator。
Comopsite的CompositeIterator同样实现了接口Iterator,同样有hasNext和next。不同的是它会(以递归的方式)遍历以composite为根的树上的所有结点。
而Leaf的iterator是一个
空对象:
- class NullIterator : public Iterator
- {
- public:
- virtual bool hasNext() { return false; }
- virtual Object* next() { return NULL; }
- };
空对象的好处是避免了过多的NULL判断。如果Leaf::CreateIterator可以返回NULL的话,那我们就要在每一个createIterator调用后判断一下返回值是否为NULL。有了空对象后就可以把NullObject当成普通对象来用。
阅读(886) | 评论(0) | 转发(0) |