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

来源:互联网 发布:1962中印战争 知乎 编辑:程序博客网 时间:2024/06/03 19:14



//---------------------------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
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 我微信冻结了怎么办 微信账号冻结了怎么办 微信被冻结里面的钱怎么办 微信账户冻结了怎么办 微信公众号忘记密码怎么办 网课没有刷完怎么办 形势与政策挂了怎么办 苹果录屏声音小怎么办 老师跟学生家长吵起来了怎么办 蓝幕拍摄抠像有蓝色怎么办 学东西悟性不高怎么办 微商不会写笔记怎么办 布鞋买大了一码怎么办 凉鞋买大了一码怎么办 皮鞋小了一码怎么办妙招 图书馆借的书本损坏了怎么办 把人打伤没钱赔怎么办 小孩不小心打伤了老师怎么办 高考进了三段怎么办 工作中和领导产生冲突怎么办 酒店不给员工发工资怎么办 裙子没有解开超市的锁怎么办 接待老外听不懂他说的怎么办 脚脱皮又痒又臭怎么办 成都应聘平面模特被骗了怎么办 文明6开场一堆蛮族怎么办 幼儿园里出了水痘怎么办 穿高跟鞋脚容易出汗怎么办 粗跟鞋走路太响怎么办 粗跟鞋鞋跟很响怎么办 皮鞋跟走路太响怎么办 穿高跟鞋脚崴了怎么办 高跟鞋小了一码怎么办 高跟皮鞋磨脚怎么办 大同同煤集团三供一业人员怎么办 小孩被猫咪抓了怎么办 长得特别丑的人怎么办 锅巴放的不脆了怎么办 淘宝买到假货了怎么办 单位不给解约函怎么办 安卓个人热点打不开怎么办