当前位置:网站首页>17 iterator mode

17 iterator mode

2022-06-22 08:30:00 Grow some hair.

Reprint of the original :https://blog.csdn.net/sinat_21107433/article/details/102879383

Write a lot of code using arrays or similar collection objects ? How to traverse the array every time ?For loop ! perhaps while loop , One by one, the elements that access each location , Until the end of the array .STL There are even special iterators in it , For specific collection class objects , There are corresponding iterators used .STL The iterator of provides rich traversal methods , Such as accessing the first element of the collection object 、 Last element 、 The element of the specified location 、 The next element …… What about? , Does it feel like you have an iterator , Traversal methods are no longer difficult ?

1. An overview of the iterator pattern
Traversal is often used in daily coding , It is usually necessary for a collection with many object instances ( Called aggregate object ) To access or obtain . For example, the first element of the aggregate object should be taken 、 Determine whether to wait at the end of the aggregate object . Traversal of aggregate objects , The iterator pattern is a very effective solution , It is also a frequently used design pattern .

Iterator pattern :

Provides a way to access elements in an aggregate object sequentially , Without exposing the internal representation of the object .

  By introducing iterators , The traversal of data can be separated from the aggregation object , thus , Aggregate objects are only responsible for storing data , The iterator object is responsible for traversing the data , Make the responsibility of the aggregated object more single , Comply with the single responsibility principle .

2. Iterator pattern structure
The iterator pattern structure includes two levels of aggregation and iterator . For the convenience of expansion , Iterator patterns are often combined with factory method patterns . Iterator pattern UML The graph is as follows . The picture shows that , The iterator pattern has the following roles :

Iterator( Abstract iterator ): It declares the interface to access and traverse the elements of the aggregate object , Such as first() Method is used to access the first element in the aggregate object ,next() Method is used to access the next element ,hasNext() Determine if there is another element ,currentItem() Method to get the current element .
ConcreteIterator( Specific iterators ): Implement the method of abstract iterator declaration , Usually, a special variable is used in a specific iterator ( Called a cursor ) To record the position of the iterator in the aggregate object .
Aggregate( Abstract aggregate class ): Used to store and manage element objects , Declare an interface for creating iterators , It's actually the role of an abstract iterator factory .
ConcreteAggregate( Concrete aggregate class ): Realized the method createIterator(), This method returns a concrete iterator corresponding to the concrete aggregate class ConcreteIterator Example .


3. Iterator pattern code instance
TV remote controller is a practical application of iterator , It can be used to traverse the TV channel set , A television can be seen as an aggregate of stored channels . This case Jungle The iterator mode will be used to simulate the process of remote control operating TV channels .

Obviously , The remote control is a concrete iterator , Has the previous channel previous() 、 The next channel next()、 Current channel currentChannel() And so on ; The aggregate object to be traversed is the collection of TV channels , Television . In this case UML The graph is as follows :

3.1. Abstract aggregate classes and concrete aggregate classes
#ifndef __AGGREGATE_H__
#define __AGGREGATE_H__
 
#include <vector>
using namespace std;
 
// Forward statement , Because the two classes refer to each other
class Iterator;
class RemoteControl;
 
// Abstract aggregate class Aggregate
class Aggregate
{
public:
    Aggregate(){}
    virtual Iterator* createIterator() = 0;
};
 
// Concrete aggregate class Television
class Television :public Aggregate
{
public:
    Television();
    Television(vector<string> iChannelList);
    // Implementation creates iterators
    Iterator* createIterator();
    // Get the total number of channels
    int getTotalChannelNum();
    void play(int i);
private:
    vector<string> channelList;
};
 
#endif //__AGGREGATE_H__
Realization :

#include "Iterator.h"
 
Television::Television(){}
 
Television::Television(vector<string> iChannelList){
    this->channelList = iChannelList;
}
 
Iterator* Television::createIterator(){
    RemoteControl *it = new RemoteControl();
    it->setTV(this);
    return (Iterator*)it;
}
 
int Television::getTotalChannelNum(){
    return channelList.size();
}
 
void Television::play(int i){
    printf(" Now play :%s……\n", channelList[i].c_str());
}
 3.2. Abstract iterator
// Abstract iterator
class Iterator
{
public:
    Iterator(){}
    // Declare Abstract traversal methods
    virtual void first() = 0;
    virtual void last() = 0;
    virtual void next() = 0;
    virtual void previous() = 0;
    virtual bool hasNext() = 0;
    virtual bool hasPrevious() = 0;
    virtual void currentChannel() = 0;
};
3.3. Specific iterators :RemoteControl
// The remote control : Specific iterators
class RemoteControl :public Iterator
{
public:
    RemoteControl(){}
    void setTV(Television *iTv){
        this->tv = iTv;
        cursor = -1;
        totalNum = tv->getTotalChannelNum();
    }
    // Implement each traversal method
    void first(){
        cursor = 0;
    }
    void last(){
        cursor = totalNum - 1;
    }
    void next(){
        cursor++;
    }
    void previous(){
        cursor--;
    }
    bool hasNext(){
        return !(cursor == totalNum);
    }
    bool hasPrevious(){
        return !(cursor == -1);
    }
    void currentChannel(){
        tv->play(cursor);
    }
private:
    // The cursor
    int cursor;
    // Total number of channels
    int totalNum;
    // TV
    Television* tv;
};
3.4. Client code examples and results  
#include <iostream>
#include "Iterator.h"
 
int main()
{
    vector<string> channelList = { " News Channel ", " Financial channel ", " Sports channel ", " The movie channel ", " Music channel ", " Agriculture channel ", " Sichuan satellite TV ", " Chengdu satellite TV " };
    // Create TV
    Television *tv = new Television(channelList);
    // Create remote control
    Iterator *remoteControl = tv->createIterator();
 
    // Sequential traversal
    printf(" Sequential traversal :\n");
    remoteControl->first();
    // Traverse all TV channels
    while (remoteControl->hasNext()){
        remoteControl->currentChannel();
        remoteControl->next();
    }
 
    printf("\n\n");
 
    // Traversal in reverse order
    printf(" Traversal in reverse order :\n");
    remoteControl->last();
    // Traverse all TV channels
    while (remoteControl->hasPrevious()){
        remoteControl->currentChannel();
        remoteControl->previous();
    }
 
    printf("\n\n");
    system("pause");
    return 0;
}
The results are as follows :

 4. summary
Looking at the code above, you can see , Iterator classes and aggregate classes contain and reference each other , So you need to forward declare a class in your code ( See above for specific operation , For code resources, see https://github.com/FengJungle/DesignPattern).

advantage :

Supports traversing an aggregate object in different ways , Multiple traversal methods can be defined on the same aggregate object .
Simplifies aggregation classes , Make the responsibility of aggregation class more single ;
An abstraction layer is introduced into the iterator pattern , Easy to add new iterator classes , To facilitate extension , Comply with opening and closing principle .
shortcoming :

Separate the responsibilities of storing objects and managing objects in the aggregation class , When adding new aggregate classes, you also need to consider adding corresponding new iterator classes , The number of classes increases in pairs , It is not conducive to system management and maintenance ;
The design is difficult , Future system expansion needs to be fully considered .
Apply to the environment :

Consider using iterator mode in the following scenarios :

Access an aggregate object without exposing its internal structure ;
You need to provide multiple traversal methods for an aggregate object .

原网站

版权声明
本文为[Grow some hair.]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/173/202206220821492934.html