Pattern Motive (Iterator pattern) : When accessing an object of an aggregate class, such as List,queue, we always want to have a unified access interface, or to implement unified access to multiple aggregate class objects, or to implement a variety of different access methods to an aggregate class, at which point the iterator pattern can meet our needs.
An iterator provides a way to access an aggregate class object without exposing its internal structure.
In general, an iterator is closely linked to an aggregation class. How do you implement only allow iterators to access the internal data of an aggregate class and avoid other classes of access? It is necessary to use the Friend class in C + + to make the iterator class A friend of the aggregate class to achieve this goal.
The following issues need to be considered when specific iterators are implemented:
1 " whether the iterative traversal process is controlled by an iterator or by the user
When controlled by the user, this iterator is called an external iterator. At this point, the customer must be responsible for moving forward the traversal process, explicitly requesting the next element to the iterator, or, if controlled by an iterator, an internal iterator. At this point, the iterator automatically executes the client-specified action on each element in the aggregation object.
In most cases, external iterators are more flexible than internal iterators and can accommodate multiple different types of aggregate class objects and are easier to extend.
2 " Whether the traversal algorithm is defined by an iterator or by the aggregate class itself
If the iterator is responsible for traversing the algorithm, then it is easy to use different iterative algorithms on the same aggregation class, but also easy to use the same iterative algorithm on different aggregation classes, and if the aggregation class itself defines an iterative algorithm, then the iterator is only responsible for storing the current state of the traversal, which is equivalent to a pointer to the current state. So we call this iterator a cursor.
To extend the versatility of iterators, we often use a polymorphic iterator type, which has both an abstract iterator interface and a specific iterator implementation class. For different types of aggregation objects, you can implement classes using different types of iterators, which requires the use of Factory mode to allocate iterator objects. At this point, there is another problem, the assigned iterator who is responsible for the deletion. If the user is responsible, a memory leak can occur because the program can be complex and forget the delete, or the program has an exception before the delete. So how to solve it?
The method is to allocate an iterator agent on the stack by using the proxy mode, which is responsible for removing the allocated space on the heap. This allows all allocated space to be freed when the program ends. To define this iterator proxy, you must do the following:
1> support for dereference operations *
2> Assignment operation =
Operation 3>
4> compare operations, such as! =/=
5> self-increment operation + +
For the sake of brevity of the code, we only overload the operations, and we need to declare the copy constructor and the assignment operator as private, which prevents the same object from being delete multiple times and prevents the compiler from providing a default implementation.
Pattern Structure diagram:
Pattern Code:
Bt_ iterative mode. h:
1 #ifndef Ip_h2 #defineIp_h3#include <iostream>4#include <string>5 using namespacestd;6 7 /*8 Abstract iterators9 */Ten classIterator One { A Public: - Virtual~Iterator () {} - Virtual voidFirst () =0; the Virtual voidNext () =0; - Virtual BOOLIsDone () =0; - Virtual CharCurrentItem () =0; - }; + - /* + Abstract Aggregation Classes A */ at classAggregate - { - Public: - Virtual~Aggregate () {} - Virtualiterator* createiterator () =0; - Virtual intCount ()Const=0; in Virtual CharGet (intIndexConst=0; - }; to + - /* the Specific iterators * */ $ classConcreteiterator: PublicIteratorPanax Notoginseng { - Public: theConcreteiterator (ConstAggregate* a): Aggregate (a), Currentindex (0){ } + Virtual voidFirst () {currentindex =0; } A Virtual voidNext () {currentindex++; } the Virtual BOOLIsDone () {returnCurrentindex >= aggregate->Count ();} + Virtual CharCurrentItem () - { $ if(IsDone ()) $ { -cout <<"traversed completed"<<Endl; - return 0; the } - ElseWuyi returnAggregate->Get (currentindex); the } - Wu Private: - const aggregate* Aggregate; About intCurrentindex; $ }; - - /* - Specific aggregation classes A */ + classConcreteaggregate: PublicAggregate the { - Public: $Concreteaggregate (stringstr) {name =str;} the virtual iterator* createiterator () () [Concreteiterator] (this); - Virtual intCount ()Const{returnname.size ();} in Virtual CharGet (intIndexConst{returnname.at (index);}; the the Private: About stringname; the }; the the #endif //Ip_h
Test case. CPP:
1#include"bt_ iterator mode. h"2 intMain ()3 {4cout <<"* * * * iterator Mode Test * * * *"<<Endl;5 stringName"Benxintuzi");6aggregate* Aggregate =Newconcreteaggregate (name);7iterator* iter =NewConcreteiterator (aggregate);8 for(Iter->first ();!iter->isdone (); iter->Next ())9cout << Iter->currentitem () <<Endl;Ten One Deleteiter; A Deleteaggregate; - - return 0; the}
Mode extension:
The iterator pattern is extended so that the allocated memory can be freed by the iterator agent itself, rather than relying on the customer's manual action. Define the proxy classes as follows:
// ...classIteratorptr/*proxy class for iterators*/{ Public: Iteratorptr (Iterator*it): iter (IT) {}~iteratorptr () {DeleteIter }//to delete an iterator on a heapiterator*operator() {returniter;}Private: Iteratorptr (Constiteratorptr&); Iteratorptr&operator=(Constiteratorptr&);Private: Iterator*iter;};// ...intMain () {cout<<"* * * * Iterator proxy mode Test * * * *"<<Endl; stringName"Benxintuzi"); Aggregate* Aggregate =Newconcreteaggregate (name); iteratorptr iterptr (aggregate ->createiterator ()); The iterator is wrapped and the proxy class is specified on the stack, and the proxy class object is automatically reclaimed after the program ends for(Iterptr->first ();!iterptr->isdone (); iterptr->Next ()) cout<< (Iterptr->currentitem ()) <<Endl; return 0;}
Model Summary:
:: Supports traversing an aggregation class in different ways, simply defining the concrete implementation class of an abstract iterator to change the traversal method.
:: The iterator pattern simplifies the interface of the aggregation class so that the aggregation class itself no longer has to maintain the cost of how it is traversed.
:: On the same aggregation class, multiple traversal operations can be performed at the same time through different iterator instances, without affecting each other.
17 Behavioral Mode-----Iterator mode