Presentation is loading. Please wait.

Presentation is loading. Please wait.

Behavioral Pattern: Iterator C h a p t e r 5 – P a g e 159 Software can become difficult to manage when a variety of different traversals of a variety.

Similar presentations


Presentation on theme: "Behavioral Pattern: Iterator C h a p t e r 5 – P a g e 159 Software can become difficult to manage when a variety of different traversals of a variety."— Presentation transcript:

1

2 Behavioral Pattern: Iterator C h a p t e r 5 – P a g e 159 Software can become difficult to manage when a variety of different traversals of a variety of different data structures is needed. The Iterator Pattern accomplishes this without burdening the interfaces of the data structures with different traversal operations, while also providing a uniform interface for traversing various data structures (i.e., iterative polymorphism).

3 The Iterator Pattern C h a p t e r 5 – P a g e 160 The Iterator defines an interface for accessing and traversing elements of an Aggregate object. The ConcreteIterator implements the Iterator interface and keeps track of the current position in the traversal of the Aggregate. The Aggregate defines an interface for creating an Iterator object. The ConcreteAggregate implements the Iterator creation interface to return an instance of the proper ConcreteIterator.

4 C h a p t e r 5 – P a g e 161 Iterator Example: Web Scraper Web pages are separated into two categories: well-formed XML documents using tags to identify specific page elements (hyperlinks, images, etc.), and regular text pages using regular expressions to identify elements. The web scraper model contains concrete aggregate objects of both types, each of which has a pair of associate concrete iterators, one for collecting hyperlinks and one for collecting images. In this model, the Client has a uniform interface for harvesting different types of tags from websites.

5 C h a p t e r 5 – P a g e 162 Stack/Queue Iterator Code in C++ #include using namespace std; class ListAggregate { public: friend class Iter; virtual Iter *createIterator() const = 0; friend ostream& operator << (ostream &outputFile, const ListAggregate &la); }; class Iter { public: virtual void first() = 0; virtual void next() = 0; virtual bool isDone() = 0; virtual int currentItem() = 0; private: const ListAggregate *listAgg; int index; };

6 C h a p t e r 5 – P a g e 163 class Stack : public ListAggregate { public: friend class StackIter; Stack() { topIndex = -1; } void push(int in) { items[++topIndex] = in; } int pop() { return items[topIndex--]; } bool isEmpty() { return (topIndex == -1); } Iter *createIterator() const; private: int items[10]; int topIndex; }; class StackIter : public Iter { public: StackIter(const Stack *s) { stk = s; } void first() { index = stk->topIndex; } void next() { index--; } bool isDone() { return index == -1; } int currentItem() { return stk->items[index]; } private: const Stack *stk; int index; }; Iter *Stack::createIterator() const { return new StackIter(this); }

7 C h a p t e r 5 – P a g e 164 class Queue : public ListAggregate { public: friend class QueueIter; Queue() { rearIndex = -1; } void enqueue(int in) { items[++rearIndex] = in; } int dequeue() { int value = items[0]; for (int i = 0; i < rearIndex; i++) items[i] = items[i+1]; rearIndex--; return value; } bool isEmpty() { return (rearIndex == -1); } Iter *createIterator() const; private: int items[10]; int rearIndex; }; class QueueIter : public Iter { public: QueueIter(const Queue *q) { que = q; } void first() { index = 0; } void next() { index++; } bool isDone() { return index == que->rearIndex + 1; } int currentItem() { return que->items[index]; } private: const Queue *que; int index; }; Iter *Queue::createIterator() const { return new QueueIter(this); }

8 C h a p t e r 5 – P a g e 165 ostream& operator << (ostream &outputFile, const ListAggregate &la) { Iter *it = la.createIterator(); for (it->first(); !it->isDone(); it->next()) outputFile currentItem(); delete it; return outputFile; } bool operator == (const ListAggregate &l, const ListAggregate &r) { Iter *itl = l.createIterator(); Iter *itr = r.createIterator(); for (itl->first(), itr->first(); !itl->isDone(); itl->next(), itr->next()) if (itl->currentItem() != itr->currentItem()) break; bool ans = itl->isDone() && itr->isDone(); delete itl; delete itr; return ans; } void main() { Stack s1; Queue q1; int i; for (i = 1; i < 5; i++) s1.push(i); for (i = 4; i > 0; i--) q1.enqueue(i); Stack s2(s1), s3(s1), s4(s1); Queue q2(q1), q3(q1), q4(q1); s3.pop(); s4.push(7); q3.dequeue(); q4.enqueue(7);

9 C h a p t e r 5 – P a g e 166 cout << "Stacks: #1 (" << s1 << ") #2(" << s2 << ") #3 (" << s3 << ") #4 (" << s4 << ")\n"; cout << "Queues: #1 (" << q1 << ") #2(" << q2 << ") #3 (" << q3 << ") #4 (" << q4 << ")\n\n"; cout << "Are Stack 1 and Stack 1 equal? " << ((s1 == s1) ? "YES!" : "NO! ") << endl; cout << "Are Stack 1 and Stack 2 equal? " << ((s1 == s2) ? "YES!" : "NO! ") << endl; cout << "Are Stack 1 and Stack 3 equal? " << ((s1 == s3) ? "YES!" : "NO! ") << endl; cout << "Are Stack 1 and Stack 4 equal? " << ((s1 == s4) ? "YES!" : "NO! ") << endl; cout << "Are Stack 1 and Queue 1 equal? " << ((s1 == q1) ? "YES!" : "NO! ") << endl; cout << "Are Stack 1 and Queue 2 equal? " << ((s1 == q2) ? "YES!" : "NO! ") << endl; cout << "Are Stack 1 and Queue 3 equal? " << ((s1 == q3) ? "YES!" : "NO! ") << endl; cout << "Are Stack 1 and Queue 4 equal? " << ((s1 == q4) ? "YES!" : "NO! ") << endl << endl; cout << "Are Stack 2 and Stack 2 equal? " << ((s2 == s2) ? "YES!" : "NO! ") << endl; cout << "Are Stack 2 and Stack 3 equal? " << ((s2 == s3) ? "YES!" : "NO! ") << endl; cout << "Are Stack 2 and Stack 4 equal? " << ((s2 == s4) ? "YES!" : "NO! ") << endl; cout << "Are Stack 2 and Queue 1 equal? " << ((s2 == q1) ? "YES!" : "NO! ") << endl; cout << "Are Stack 2 and Queue 2 equal? " << ((s2 == q2) ? "YES!" : "NO! ") << endl; cout << "Are Stack 2 and Queue 3 equal? " << ((s2 == q3) ? "YES!" : "NO! ") << endl; cout << "Are Stack 2 and Queue 4 equal? " << ((s2 == q4) ? "YES!" : "NO! ") << endl << endl; cout << "Are Stack 3 and Stack 3 equal? " << ((s3 == s3) ? "YES!" : "NO! ") << endl; cout << "Are Stack 3 and Stack 4 equal? " << ((s3 == s4) ? "YES!" : "NO! ") << endl; cout << "Are Stack 3 and Queue 1 equal? " << ((s3 == q1) ? "YES!" : "NO! ") << endl; cout << "Are Stack 3 and Queue 2 equal? " << ((s3 == q2) ? "YES!" : "NO! ") << endl; cout << "Are Stack 3 and Queue 3 equal? " << ((s3 == q3) ? "YES!" : "NO! ") << endl; cout << "Are Stack 3 and Queue 4 equal? " << ((s3 == q4) ? "YES!" : "NO! ") << endl << endl; cout << "Are Stack 4 and Stack 4 equal? " << ((s4 == s4) ? "YES!" : "NO! ") << endl; cout << "Are Stack 4 and Queue 1 equal? " << ((s4 == q1) ? "YES!" : "NO! ") << endl; cout << "Are Stack 4 and Queue 2 equal? " << ((s4 == q2) ? "YES!" : "NO! ") << endl; cout << "Are Stack 4 and Queue 3 equal? " << ((s4 == q3) ? "YES!" : "NO! ") << endl; cout << "Are Stack 4 and Queue 4 equal? " << ((s4 == q4) ? "YES!" : "NO! ") << endl << endl; cout << "Are Queue 1 and Queue 1 equal? " << ((q1 == q1) ? "YES!" : "NO! ") << endl; cout << "Are Queue 1 and Queue 2 equal? " << ((q1 == q2) ? "YES!" : "NO! ") << endl; cout << "Are Queue 1 and Queue 3 equal? " << ((q1 == q3) ? "YES!" : "NO! ") << endl; cout << "Are Queue 1 and Queue 4 equal? " << ((q1 == q4) ? "YES!" : "NO! ") << endl << endl; cout << "Are Queue 2 and Queue 2 equal? " << ((q2 == q2) ? "YES!" : "NO! ") << endl; cout << "Are Queue 2 and Queue 3 equal? " << ((q2 == q3) ? "YES!" : "NO! ") << endl; cout << "Are Queue 2 and Queue 4 equal? " << ((q2 == q4) ? "YES!" : "NO! ") << endl << endl; cout << "Are Queue 3 and Queue 3 equal? " << ((q3 == q3) ? "YES!" : "NO! ") << endl; cout << "Are Queue 3 and Queue 4 equal? " << ((q3 == q4) ? "YES!" : "NO! ") << endl << endl; cout << "Are Queue 4 and Queue 4 equal? " << ((q4 == q4) ? "YES!" : "NO! ") << endl << endl; }

10 C h a p t e r 5 – P a g e 167

11 Iterator Pattern Advantages C h a p t e r 5 – P a g e 168 The Iterator Pattern provides ways to access elements of an aggregate object sequentially without exposing the underlying structure of the object. The Iterator abstraction is fundamental to an emerging technology called “generic programming”, which seeks to explicitly separate the notion of "algorithm" from that of "data structure". The motivation is to promote component- based development, to boost productivity, and to reduce configuration management. One drawback of iterators is that they give the illusion of order to unordered structures. For example, a set does not support ordering, and its Iterator would likely traverse the elements in an arbitrary sequence that could change over time. Program developers must be careful to produce code that does not assume consistency in the underlying structure.


Download ppt "Behavioral Pattern: Iterator C h a p t e r 5 – P a g e 159 Software can become difficult to manage when a variety of different traversals of a variety."

Similar presentations


Ads by Google