zoukankan      html  css  js  c++  java
  • 设计模式 笔记 迭代器模式 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;

    }




  • 相关阅读:
    【转】Ubuntu 20.04修改ip地址
    试用 Portable Allegro Serve
    看完了 Source Code
    Common Lisp 参数传递的几种形式
    Irony 一个 .NET 语言实现工具包
    PPT 技巧学习
    LISP 练习:quick sort
    关于 Business Rule Engine
    转换 PDF 格式为适合电纸书阅读的版本
    IIS 7 SMTP configuration
  • 原文地址:https://www.cnblogs.com/boydfd/p/4983120.html
Copyright © 2011-2022 走看看