设计模式 笔记 迭代器模式 Iterator



//---------------------------15/04/26----------------------------


//Iterator 迭代器模式----对象行为型模式


/*

    1:意图:

        提供一种方法顺序访问一个聚合对象中各个元素,而又不需暴露该对象的内部表示。

    2:别名:

        游标(Cursor)

    3:动机:

    4:适用性:

        1>访问一个聚合对象的内容而无需暴露它的内部表示。

        2>支持对聚合对象的多种遍历。

        3>为遍历不同的聚合结构提供一个统一的接口。

    5:结构:

        Aggregate:<-------------Client----------------->Iterator:

        CreateIterator()                                First()

            |                                           Next()

            |                                           IsDone()

            |                                           CurrentItem()

            |                                               |

        ConcreteAggregate()- - - - - - - - - - - - - ->ConcreteIterator

        CreateIterator()   <------------------------------|

        { return new ConcreteIterator(this)}

    6:参与者:

        1>Iterator

            迭代器定义访问和遍历元素的接口。

        2>ConcreteIterator

            1)具体迭代器实现迭代器接口。

            2)对该聚合遍历时跟踪当前位置。

        3>Aggregate

            聚合定义创建相应迭代器对象的接口。

        4>ConcreteAggregate

            具体聚合实现创建相应迭代器的接口,该操作返回ConcreteIterator的一个适当的实例。

    7:协作:

        ConcreteIterator跟踪聚合中的当前对象,并能够计算出代遍历的后继对象。

    8:效果:

        1>它支持以不同的方式遍历一个聚合:

            复杂的聚合可用多种方式进行遍历。比如stl中的正常的迭代器以及反向迭代器。

        2>迭代器简化了聚合的接口:

            有了迭代器的遍历接口,聚合本身就不再需要类似的遍历接口,这样就简化了聚合的接口。

        3>在同一个聚合上可以有多个遍历:

            每个迭代器保持它自己的遍历状态。因此你可以同时进行多个遍历。

    9:实现:

        迭代器在实现上有许多变化和选择。

        1>谁控制该迭代:

            由客户来控制迭代的称为外部迭代器,由迭代器控制迭代称为内部迭代器。外部迭代器比较灵活

            内部迭代器实现起来比较简单。所以能实现还是实现为外部迭代器的。

        2>谁定义遍历算法:

            迭代器来负责遍历算法易于在相同聚合上使用不同的迭代算法,也易于在不同的聚合上重用相同的算法。

            但是因为要访问聚合中的私有变量,会破坏聚合的封装性

        3>迭代器健壮程度如何:

            插入和删除操作不能干扰别的迭代器的遍历。为了速度考虑,stl的迭代器并不都能保证这个条件。

        4>附加的迭代器操作:

            迭代器起码要有First,Next,IsDone,CurrenItem等操作,当然可以附加一些有用的操作,比如

            Previous

        5>c++中使用多态的迭代器:

            使用多态的迭代器是要付出代价的,也就是客户必须自己删除迭代器指针,所以可以使用智能指针

            也就是代理模式。

        6>迭代器可有特权访问:

            迭代器可以访问聚合的元素,所以可以声明为友元,为了防止多次声明友元,可以定义一个abstract

            的迭代器,然后由只要继承这个类就能行了。

        7>用于复合对象的迭代器:

            Composite模式中,那些递归聚合结构上,外部迭代器难以实现,因为该结构中不同对象处于嵌套

            聚合的多个不同层次,因此一个外部迭代器为跟踪对象必须存储一条纵贯该composite的路径。

        8>空迭代器:

            一个空迭代器是一个退化的迭代器,它可以帮助处理边界条件,也就是stl中的end()

  10:代码示例:                                                                        */



//Aggregate:定义了一些接口

template<class Item>

class List

{

public:

    List(long size= DEFAULT_LIST_CAPACITY);

    long Count() const;

    Item& Get(long index) const;

};


//abstract Iterator:定义迭代器的接口

template<class Item>

class Iterator

{

public:

    virtual void First() = 0;

    virtual void Next() = 0;

    virtual bool IsDone() const = 0;

    virtual Item CurrenItem() const = 0;

protected:

    Iterator();

};


//ConcreteIterator

template<class Item>

class ListIterator : public Iterator<Item>

{

public:

    ListIterator(const List<Item>* aList);

    virtual void First();

    virtual void Next();

    virtual bool IsDone() const;

    virtual Item CurrenItem() const;

private:

    const List<Item>* _list;

    long _current;

}


//只要把当前的位置设置为0就是第一个

template<class Item>

void ListIterator<Item>::First()

{

    _current = 0;

}


//下一个就是把位置加一

template<class Item>

void ListIterator<Item>::Next()

{

    _current++;

}


//如果完成了,说明当前位置大于等于list中的元素了

template<class Item>

bool ListIterator<Item>::IsDone() const

{

    return _current >= _list->Count();

}


//只要当前的位置小于元素数量,就返回当前元素。

template<class Item>

Item ListIterator<Item>::CurrenItem() const

{

    if(IsDone())

       throw IteratorOutofBounds;

       return _list->Get(_current);

}


//这是一个客户自定义打印函数

void PrintEmployees(Iterator<Employee*>& i)

{

    for(i.First(); !i.IsDone(); i.Next())

        i.CurrenItem()->Print();

}


//定义一个指向指针list

List<Employee*>* employee;

//...


//定义迭代器

ListIterator<Employee*> forward(employee);

ReverseListIterator<Employee*> backward(employee);

PrintEmployees(forward);

PrintEmployees(backward);


//这是一个不同的list,但是客户需要记住不同的迭代器,会很麻烦,所以我们需要在list

//中实现一个工厂方法,它能直接返回一个abstract类型的迭代器。

SkipList<Employee*>* employees;

//...


SkipListIterator<Employee*> Iterator(employees);

PrintEmployees(iterator);


//抽象的list

template<class Item>

class AbstractList

{

public:

    virtual Iterator<Item>* CreateIterator() const = 0;

};



template<class Item>

Iterator<Item>* List<Item>::CreateIterator() const

{

    return new ListIterator<Item>(this);

}


//这样可以不使用具体迭代器类型,直接使用list对象的create函数来创造一个迭代器。

AbstractList<Employee*>* employee;


Iterator<Employee*>* iterator = employee->CreateIterator();

PrintEmployees(*iterator);

delete iterator;


//为了保证迭代器被删除,可以使用智能指针

template<class Item>

class IteratorPtr

{

public:

    IteratorPtr(Iterator<Item>* i): _i(i){}

    _IteratorPtr(){delete _i};

    

    //每个智能指针都要实现的两个重载

    Iterator<Item>* operator->() { return _i;}

    Iterator<Item>* operator*() { return *_i;}

private:

    IteratorPtr(const IteratorPtr&);

    IteratorPtr& operator=(const IteratorPtr&);

    

private:

    Iterator<Item>* _i;

};


//这样就不需要delete了。

AbstractList<Employee*>* employee;


IteratorPtr<Employee*>* iterator = employee->CreateIterator();

PrintEmployees(*iterator);


//一个内部的ListIterator 遍历操作在内部实现

template<class Item>

class ListTraverser

{

public:

    ListTraverser(List<Item>* aList);

    bool Traverse();

protected:

    virtual bool ProcessItem(const Item&) = 0;

private:

    ListIterator<Item> _iterator;

};



template<class Item>

ListTraverser<Item>::ListTraverser(List<Item>* aList)

    :_iterator(aList){}


//遍历操作

template<class Item>

bool ListTraverser<Item>::Traverse()

{

    bool result = false;

    for(_iterator.First(); !_iterator.IsDone(); _iterator.Next())

    {

        result = ProcessItem(_iterator.CurrenItem());

        if(result == false)

            break;

    }

    return result;

}


//如果需要打印不同的链表,必须实现不同的迭代器,所以内部迭代器实现会比较麻烦。

class PrintNEmployees : public ListTraverser<Employee*>

{

public:

    PrintNEmployees(List<Employee*>* aList, int n)

    :   ListTraverser<Employee*>(aList), _total(n), _count(0){}

protected:

    bool ProcessItem(Employee* const&);

    

private:

    int _total;

    int _count;

}


bool PrintNEmployees::ProcessItem(Employee* const& e)

{

    _count++;

    e->Print();

    return _count < _total;

}

//这里就不需要自己实现遍历函数,直接调用内部迭代器的函数打印。

List<Employee*>* employees;


PrintNEmployees pa(employees, 10);

pa.Traverse();


ListIterator<Employee*> i(employees);


//下面是外部迭代器的打印过程,必须自己实现逻辑

int count = 0;


for(i.First(); !i.IsDone(); i.Next())

{

    count++;

    i.CurrenItem()->Print();

    if(count >= 10)

    {

        break;

    }

}

//这个迭代器可以过滤一些元素,只有通过测试菜能打印出来

template<class Item>

class FilteringListTraverser

{

public:

    FilteringListTraverser(List<Item>* aList);

    bool Traverse();

protected:

    virtual bool ProcessItem(const Item&) = 0;

    virtual bool TestItem(const Item&) = 0;

private:

    ListIterator<Item> _iterator;

};


template<class Item>

void FilteringListTraverser<Item>::Traverse()

{

    bool result = false;

    for(_iterator.First(); !=_iterator.IsDone(); _iterator.Next())

    {

        //先测试

        if(TestItem(_iterator.CurrenItem()))

           {

               result = ProcessItem(_iterator.CurrenItem());

               if(result == false)

                   break;

           }

    }

    return result;

}




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值