Design Mode note Iterator mode Iterator
// Iterator mode ---- object behavior mode
/*
1: Intention:
Provides a method to access each element in an aggregate object sequentially without exposing the internal representation of the object.
2: alias:
Cursor)
3: motivation:
4: Applicability:
1> access the content of an aggregate object without exposing its internal representation.
2> supports multiple traversal of aggregate objects.
3> provides a unified interface for Traversing different aggregation structures.
5: structure:
Aggregate: <------------- Client -----------------> Iterator:
CreateIterator () First ()
| Next ()
| IsDone ()
| CurrentItem ()
|
ConcreteAggregate ()--> ConcreteIterator
CreateIterator () <------------------------------ |
{Return new ConcreteIterator (this )}
6: participants:
1> Iterator:
The iterator defines interfaces for accessing and traversing elements.
2> ConcreteIterator:
1) The specific iterator implements the iterator interface.
2) track the current position of the aggregation time.
3> Aggregate:
Aggregate defines the interface for creating the corresponding iterator object.
4> ConcreteAggregate:
The specific aggregation implementation creates an interface for the corresponding iterator. This operation returns an appropriate instance of ConcreteIterator.
7: collaboration:
ConcreteIterator tracks the current object in the aggregation, and can calculate the next object of generation traversal.
8: effect:
1> it supports traversing an aggregation in different ways:
Complex aggregation can be traversed in multiple ways. For example, normal iterators and reverse iterators in stl.
2> the iterator simplifies the aggregation interface:
With the traversal interface of the iterator, the aggregation itself does not need similar traversal interfaces, which simplifies the aggregation interface.
3> multiple traversal can be performed on the same aggregation:
Each iterator maintains its own traversal status. Therefore, you can perform multiple traversal at the same time.
9: Implementation:
The iterator has many changes and choices in implementation.
1> who controls the iteration:
The external iterator controlled by the customer is called the internal iterator, And the iteration controlled by the iterator is called the internal iterator. Flexible external iterator
The internal iterator is easy to implement. Therefore, it can be implemented as an external iterator.
2> who defines the traversal algorithm:
The iterator is responsible for Traversing algorithms. It is easy to use different iterative algorithms on the same aggregation, and it is easy to reuse the same algorithms on different aggregation.
However, to access the private variables in the aggregation, The encapsulation of the aggregation will be broken.
3> how robust the iterator is:
The insert and delete operations cannot interfere with the traversal of other iterators. For speed consideration, the stl iterator does not guarantee this condition.
4> additional iterator operations:
The iterator must have at least First, Next, IsDone, CurrenItem, and other operations. Of course, some useful operations can be attached, such
Previous
5> use a multi-state iterator in c ++:
Multi-state iterators are costly, that is, the customer must delete the iterator pointer, so smart pointers can be used.
That is, the proxy mode.
6> the iterator can have privileged access:
The iterator can access aggregated elements, so it can be declared as friends. To prevent multiple declarations of friends, you can define a abstract
The iterator, and then the class can be inherited.
7> iterators used for composite objects:
In Composite mode, external iterators are difficult to implement in recursive aggregate structures because different objects in the structure are nested.
So an external iterator must store a path that runs through the composite for the tracking object.
8> Empty iterator:
An empty iterator is a degraded iterator that can help process boundary conditions, that is, end () in stl ().
Tip 10: Sample Code :*/
// Aggregate: defines some interfaces.
Template
Class List
{
Public:
List (long size = DEFAULT_LIST_CAPACITY );
Long Count () const;
Item & Get (long index) const;
};
// Abstract Iterator: defines the Iterator Interface
Template
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 ListIterator: public Iterator
{
Public:
ListIterator (const List * AList );
Virtual void First ();
Virtual void Next ();
Virtual bool IsDone () const;
Virtual Item CurrenItem () const;
Private:
Const List * _ List;
Long _ current;
}
// Set the current position to 0, which is the first
Template
Void ListIterator : First ()
{
_ Current = 0;
}
// The next step is to add a position.
Template
Void ListIterator : Next ()
{
_ Current ++;
}
// If completed, the current position is greater than or equal to the element in the list.
Template
Bool ListIterator : IsDone () const
{
Return _ current> = _ list-> Count ();
}
// If the current position is smaller than the number of elements, the current element is returned.
Template
Item ListIterator : CurrenItem () const
{
If (IsDone ())
Throw IteratorOutofBounds;
Return _ list-> Get (_ current );
}
// This is a custom printing function
Void PrintEmployees (Iterator & I)
{
For (I. First ();! I. IsDone (); I. Next ())
I. CurrenItem ()-> Print ();
}
// Define a pointer list
List * Employee;
//...
// Define the iterator
ListIterator Forward (employee );
ReverseListIterator Backward (employee );
PrintEmployees (forward );
PrintEmployees (backward );
// This is a different list, but the customer needs to remember different iterators, it will be very troublesome, so we need
// Implements a factory method, which can directly return an abstract iterator.
SkipList * Employees;
//...
SkipListIterator Iterator (employees );
PrintEmployees (iterator );
// Abstract list
Template
Class effecactlist
{
Public:
Virtual Iterator * CreateIterator () const = 0;
};
Template
Iterator * List : CreateIterator () const
{
Return new ListIterator (This );
}
// You can directly create an iterator using the create function of the list object without using the specific iterator type.
AbstractList * Employee;
Iterator * Iterator = employee-> CreateIterator ();
PrintEmployees (* iterator );
Delete iterator;
// To ensure that the iterator is deleted, you can use a smart pointer.
Template
Class IteratorPtr
{
Public:
IteratorPtr (Iterator * I): _ I (I ){}
_ IteratorPtr () {delete _ I };
// Each smart pointer must implement two reloads.
Iterator * Operator-> () {return _ I ;}
Iterator * Operator * () {return * _ I ;}
Private:
IteratorPtr (const IteratorPtr &);
IteratorPtr & operator = (const IteratorPtr &);
Private:
Iterator * _ I;
};
// Delete is not required.
AbstractList * Employee;
IteratorPtr * Iterator = employee-> CreateIterator ();
PrintEmployees (* iterator );
// An internal ListIterator: implements the traversal operation internally.
Template
Class ListTraverser
{
Public:
ListTraverser (List * AList );
Bool Traverse ();
Protected:
Virtual bool ProcessItem (const Item &) = 0;
Private:
ListIterator _ Iterator;
};
Template
ListTraverser : ListTraverser (List * AList)
: _ Iterator (aList ){}
// Traversal
Template
Bool ListTraverser : Traverse ()
{
Bool result = false;
For (_ iterator. First ();! _ Iterator. IsDone (); _ iterator. Next ())
{
Result = ProcessItem (_ iterator. CurrenItem ());
If (result = false)
Break;
}
Return result;
}
// If You Need To print different linked lists, you must implement different iterators, so it is troublesome to implement the internal iterator.
Class PrintNEmployees: public ListTraverser
{
Public:
PrintNEmployees (List * AList, int n)
: ListTraverser (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;
}
// You do not need to implement the traversal function here, and directly call the function print of the internal iterator.
List * Employees;
PrintNEmployees pa (employees, 10 );
Pa. Traverse ();
ListIterator I (employees );
// The following is the printing process of the external iterator. You must implement the logic yourself.
Int count = 0;
For (I. First ();! I. IsDone (); I. Next ())
{
Count ++;
I. CurrenItem ()-> Print ();
If (count> = 10)
{
Break;
}
}
// This iterator can filter out some elements, which can be printed only by test dishes.
Template
Class FilteringListTraverser
{
Public:
FilteringListTraverser (List * AList );
Bool Traverse ();
Protected:
Virtual bool ProcessItem (const Item &) = 0;
Virtual bool TestItem (const Item &) = 0;
Private:
ListIterator _ Iterator;
};
Template
Void FilteringListTraverser : Traverse ()
{
Bool result = false;
For (_ iterator. First ();! = _ Iterator. IsDone (); _ iterator. Next ())
{
// Test first
If (TestItem (_ iterator. CurrenItem ()))
{
Result = ProcessItem (_ iterator. CurrenItem ());
If (result = false)
Break;
}
}
Return result;
}