Iterator Pattern. CSIE Department, NTUT Chien-Hung Liu. Provide a way to access the elements of an aggregate object sequentially



Similar documents
Iterators. Provides a way to access elements of an aggregate object sequentially without exposing its underlying representation.

Binary Search Trees (BST)

Boolean Expressions, Conditions, Loops, and Enumerations. Precedence Rules (from highest to lowest priority)

JAVA COLLECTIONS FRAMEWORK

DATA STRUCTURES USING C

Ordered Lists and Binary Trees

CSI33 Data Structures

Data Structures, Practice Homework 3, with Solutions (not to be handed in)

CMSC 132: Object-Oriented Programming II. Design Patterns I. Department of Computer Science University of Maryland, College Park

How To Use The Command Pattern In Java.Com (Programming) To Create A Program That Is Atomic And Is Not A Command Pattern (Programmer)

Glossary of Object Oriented Terms

1) The postfix expression for the infix expression A+B*(C+D)/F+D*E is ABCD+*F/DE*++

Data Structures and Algorithms

CHAPTER 4 ESSENTIAL DATA STRUCTRURES

Data Structure [Question Bank]

Structural Design Patterns Used in Data Structures Implementation

16 Collection Classes

Java Software Structures

Data Structure with C

10CS35: Data Structures Using C

Questions 1 through 25 are worth 2 points each. Choose one best answer for each.

Curriculum Map. Discipline: Computer Science Course: C++

Chapter 13: Query Processing. Basic Steps in Query Processing

PART-A Questions. 2. How does an enumerated statement differ from a typedef statement?

How To Design Your Code In Php (Php)

C++FA 3.1 OPTIMIZING C++

PROBLEM SOLVING SEVENTH EDITION WALTER SAVITCH UNIVERSITY OF CALIFORNIA, SAN DIEGO CONTRIBUTOR KENRICK MOCK UNIVERSITY OF ALASKA, ANCHORAGE PEARSON

A binary search tree or BST is a binary tree that is either empty or in which the data element of each node has a key, and:

- Easy to insert & delete in O(1) time - Don t need to estimate total memory needed. - Hard to search in less than O(n) time

Copyright 2001, Bill Trudell. Permission is granted to copy for the PLoP 2001 conference. All other rights reserved.

UIL Computer Science for Dummies by Jake Warren and works from Mr. Fleming

Data Structures. Level 6 C Module Descriptor

BCS2B02: OOP Concepts and Data Structures Using C++

Binary Search Trees CMPSC 122

Node-Based Structures Linked Lists: Implementation

MAX = 5 Current = 0 'This will declare an array with 5 elements. Inserting a Value onto the Stack (Push)

C++ Crash Kurs. C++ Object-Oriented Programming

C++ INTERVIEW QUESTIONS

Binary Trees and Huffman Encoding Binary Search Trees

KITES TECHNOLOGY COURSE MODULE (C, C++, DS)

API for java.util.iterator. ! hasnext() Are there more items in the list? ! next() Return the next item in the list.

Data Structures Using C++ 2E. Chapter 5 Linked Lists

Converting a Number from Decimal to Binary

What Is Recursion? Recursion. Binary search example postponed to end of lecture

TREE BASIC TERMINOLOGIES

What is a Loop? Pretest Loops in C++ Types of Loop Testing. Count-controlled loops. Loops can be...

AP Computer Science AB Syllabus 1

Class 32: The Java Collections Framework

Lecture 9. Semantic Analysis Scoping and Symbol Table

Advanced Data Structures

Recursion. Slides. Programming in C++ Computer Science Dept Va Tech Aug., Barnette ND, McQuain WD

CS104: Data Structures and Object-Oriented Design (Fall 2013) October 24, 2013: Priority Queues Scribes: CS 104 Teaching Team

Optimal Binary Search Trees Meet Object Oriented Programming

Common Data Structures

The Tower of Hanoi. Recursion Solution. Recursive Function. Time Complexity. Recursive Thinking. Why Recursion? n! = n* (n-1)!

1. What are Data Structures? Introduction to Data Structures. 2. What will we Study? CITS2200 Data Structures and Algorithms

Chapter 14 The Binary Search Tree

root node level: internal node edge leaf node Data Structures & Algorithms McQuain

N3458: Simple Database Integration in C++11

Operator Overloading. Lecture 8. Operator Overloading. Running Example: Complex Numbers. Syntax. What can be overloaded. Syntax -- First Example

Data Structures Using C++ 2E. Chapter 5 Linked Lists

ECE 250 Data Structures and Algorithms MIDTERM EXAMINATION /5:15-6:45 REC-200, EVI-350, RCH-106, HH-139

Java 6 'th. Concepts INTERNATIONAL STUDENT VERSION. edition

CSCI 123 INTRODUCTION TO PROGRAMMING CONCEPTS IN C++

1. The memory address of the first element of an array is called A. floor address B. foundation addressc. first address D.

A DESIGN PATTERNS PERSPECTIVE ON DATA STRUCTURES. Virginia Niculescu

CS107L Handout 04 Autumn 2007 October 19, 2007 Custom STL-Like Containers and Iterators

Patterns in. Lecture 2 GoF Design Patterns Creational. Sharif University of Technology. Department of Computer Engineering

Exercises Software Development I. 11 Recursion, Binary (Search) Trees. Towers of Hanoi // Tree Traversal. January 16, 2013

Sample Questions Csci 1112 A. Bellaachia

5. A full binary tree with n leaves contains [A] n nodes. [B] log n 2 nodes. [C] 2n 1 nodes. [D] n 2 nodes.

Cpt S 223. School of EECS, WSU

Java Application Developer Certificate Program Competencies

Binary Search Trees. A Generic Tree. Binary Trees. Nodes in a binary search tree ( B-S-T) are of the form. P parent. Key. Satellite data L R

Algorithms and Data S tructures Structures Stack, Queues, and Applications Applications Ulf Leser

Linked Lists: Implementation Sequences in the C++ STL

Object Oriented Software Design II

Chapter 8: Bags and Sets

Morris School District. AP Computer Science A Curriculum Grades 9-12

CpSc212 Goddard Notes Chapter 6. Yet More on Classes. We discuss the problems of comparing, copying, passing, outputting, and destructing

CSCI 253. Object Oriented Programming (OOP) Overview. George Blankenship 1. Object Oriented Design: Java Review OOP George Blankenship.

How To Teach C++ Data Structure Programming

Multichoice Quetions 1. Atributes a. are listed in the second part of the class box b. its time is preceded by a colon. c. its default value is

Krishna Institute of Engineering & Technology, Ghaziabad Department of Computer Application MCA-213 : DATA STRUCTURES USING C

Introduction to Patterns and Frameworks

1.1.3 Syntax The syntax for creating a derived class is very simple. (You will wish everything else about it were so simple though.

Sequences in the C++ STL

Twin A Design Pattern for Modeling Multiple Inheritance

Abstract Data Type. EECS 281: Data Structures and Algorithms. The Foundation: Data Structures and Abstract Data Types

Syllabus for Computer Science. Proposed scheme for B.Sc Programme under Choice Based Credit System

Recursive Implementation of Recursive Data Structures

Storage Classes CS 110B - Rule Storage Classes Page 18-1 \handouts\storclas

C++ Programming Language

Moving from CS 61A Scheme to CS 61B Java

Java (12 Weeks) Introduction to Java Programming Language

Distributed Result Set Iterator: a design pattern for efficient retrieval of large result sets from remote data sources

PES Institute of Technology-BSC QUESTION BANK

IS0020 Program Design and Software Tools Midterm, Feb 24, Instruction

Object Oriented Design

El Dorado Union High School District Educational Services

Transcription:

Iterator Pattern CSIE Department, NTUT Chien-Hung Liu Iterator: Intent Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation Also known as Cursor 1

Iterator: Motivation (1) An aggregate object such as a list should give you a way to access its elements without exposing its internal structure might want to traverse the list in different ways, depending on what you want to accomplish don't want to bloat the List interface with operations for different traversals might also need to have more than one traversal pending on the same list Iterator: Motivation (1-1) C++ STL Example list<int> l; // vector<int> l; l.push_back(1); l.push_back(2); list<int>::iterator i; // vector <int>::iterator i for (i = l.begin(); i!= l.end(); i++) cout << *i << endl; list<int>::reverse_iterator ri; // vector<int> for (ri = l.rbegin(); ri!= l.rend(); ri++) cout << *ri << endl; 2

Iterator: Motivation (2) The key idea is to take the responsibility for access and traversal out of the list object and put it into an iterator object copyright by Design Patterns: Elements of Reusable Object-Oriented Software, Addison Wesley, 1995 Iterator: Motivation (3) Separating the traversal mechanism from the List object lets us define iterators for different traversal policies without enumerating them in the List interface. E.g., FilteringListIterator Notice that the client must know that it is a list that's traversed the client commits to a particular aggregate structure It would be better if we could change the aggregate class without changing client code by generalizing the iterator concept to support polymorphic iteration 3

Iterator: Motivation (4) Abstract List Abstract Iterator With AbstractList and abstract iterator, iteration mechanism becomes independent of concrete aggregate classes copyright by Design Patterns: Elements of Reusable Object-Oriented Software, Addison Wesley, 1995 Iterator: Motivation (5) How to create the iterator? How to write code that's independent of the concrete List subclasses? Make the list objects responsible for creating their corresponding iterator requires an operation like CreateIterator through which clients request an iterator object CreateIterator is an example of a factory method The Factory Method approach give rise to two class hierarchies, one for lists and another for iterators 4

Iterator: Applicability To access an aggregate object's contents without exposing its internal representation To support multiple traversals of aggregate objects To provide a uniform interface for traversing different aggregate structures That is, to support polymorphic iteration Iterator: Structure copyright by Design Patterns: Elements of Reusable Object-Oriented Software, Addison Wesley, 1995 5

Iterator: Participants Iterator defines an interface for accessing and traversing elements. ConcreteIterator implements the Iterator interface. keeps track of the current position in the traversal of the aggregate. Aggregate defines an interface for creating an Iterator object. ConcreteAggregate implements the Iterator creation interface to return an instance of the proper ConcreteIterator. Iterator: Collaboration A ConcreteIterator keeps track of the current object in the aggregate and can compute the succeeding object in the traversal. 6

Iterator: Consequences It supports variations in the traversal of an aggregate E.g., Code generation may traverse the parse tree inorder or preorder. Iterators make it easy to change the traversal algorithm You can also define Iterator subclasses to support new traversals Iterators simplify the Aggregate interface Iterator's traversal interface obviates the need for a similar interface in Aggregate More than one traversal can be pending on an aggregate An iterator keeps track of its own traversal state Iterator: Implementation (1) Iterator has many implementation variants and alternatives. The trade-offs often depend on the control structures your language provides. Who controls the iteration? External iterator (or active iterators) when the client controls the iteration the role of the client clients that use an external iterator must advance the traversal and request the next element explicitly from the iterator more flexible than internal iterators easy to compare two collections for equality 7

Iterator: Implementation (2) Internal iterator (or passive iterators) the iterator controls the iteration the client hands an internal iterator an operation to perform, and the iterator applies that operation to every element in the aggregate easier to use, because they define the iteration logic for you Iterator: Implementation (3) Who defines the traversal algorithm? (1) The iterator is responsible to define the traversal algorithm easy to use different iteration algorithms on the same aggregate also be easier to reuse the same algorithm on different aggregates (2) Aggregate define the traversal algorithm and use the iterator to store just the state of the iteration this kind of iterator is called a cursor since it merely points to the current position in the aggregate the traversal algorithm can access the private variables of the aggregate 8

Iterator: Implementation (4) How robust is the iterator? A robust iterator ensures that insertions and removals won't interfere with traversal it does traversal without copying the aggregate Many ways to implement robust iterators. Most rely on registering the iterator with the aggregate On insertion or removal the aggregate either adjusts the internal state of iterators, or it maintains information internally to ensure proper traversal Iterator: Implementation (4-1) How robust is the iterator? C++ STL exampe for (i = l.begin(); i!= l.end(); i++) if (*i == 5) { l.erase(i); break; l.remove(5); break is necessary (i.e., the loop can not continue) You do not need a loop to remove an element from a list 9

Iterator: Implementation (5) Additional Iterator operations The minimal interface to Iterator consists of the operations First, Next, IsDone, and CurrentItem Some additional operations might prove useful. E.g., ordered aggregates can have a Previous operation that positions the iterator to the previous element. A SkipTo operation is useful for sorted or indexed collections. SkipTo positions the iterator to an object matching specific criteria Iterator: Implementation (6) Using polymorphic iterators in C++ Polymorphic iterators have their cost require the iterator object to be allocated dynamically by a factory method should be used only when there's a need for polymorphism Otherwise use concrete iterators (allocated on the stack) Another drawback: the client is responsible for deleting them We can use a stack-allocated proxy (i.e., Proxy pattern) as a stand-in for the real iterator. (resource allocation is initialization) The proxy deletes the iterator in its destructor. Thus when the proxy goes out of scope, the real iterator will get deallocated along with it The proxy ensures proper cleanup, even in the face of exceptions 10

Iterator: Implementation (7) Iterators may have privileged access An iterator can be viewed as an extension of the aggregate that created it The iterator and the aggregate are tightly coupled We can express this close relationship in C++ by making the iterator a friend of its aggregate Iterator: Implementation (8) Iterators for composites External iterators can be difficult to implement over recursive aggregate structures like those in the Composite pattern because a position in the structure may span many levels of nested aggregates has to store a path through the Composite to keep track of the current object Sometimes it's easier just to use an internal iterator It can record the current position simply by calling itself recursively, thereby storing the path implicitly in the call stack If the nodes in a Composite have an interface for moving from a node to its siblings, parents, and children, then a cursor-based iterator may offer a better alternative. Composites often need to be traversed in more than one way. E.g., Preorder, postorder, inorder, and breadth-first traversals support each kind of traversal with a different class of iterator 11

Iterator: Implementation (9) Null iterators A NullIterator is a degenerate iterator that's helpful for handling boundary conditions By definition, a NullIterator is always done with traversal; that is, its IsDone operation always evaluates to true NullIterator can make traversing tree-structured aggregates (like Composites) easier. That lets us implement traversal over the entire structure in a uniform way At each point in the traversal, we ask the current element for an iterator for its children. Aggregate elements return a concrete iterator as usual. But leaf elements return an instance of NullIterator. Iterator: Sample Code (1) List and Iterator interfaces class List { public: List(long size = DEFAULT_LIST_CAPACITY); long Count() const; Item& Get(long index) const; //... ; class Iterator { public: virtual void First() = 0; virtual void Next() = 0; virtual bool IsDone() const = 0; virtual Item CurrentItem() const = 0; protected: Iterator(); ; 12

Iterator: Sample Code (2) class ListIterator : public Iterator<Item> { public: ListIterator(const List<Item>* alist); virtual void First(); virtual void Next(); virtual bool IsDone() const; virtual Item CurrentItem() const; private: const List<Item>* _list; long _current; ; Iterator subclass implementations Iterator: Sample Code (3) ListIterator<Item>::ListIterator ( const List<Item>* alist ) : _list(alist), _current(0) { void ListIterator<Item>::First () { _current = 0; void ListIterator<Item>::Next () { _current++; bool ListIterator<Item>::IsDone () const { return _current >= _list->count(); Item ListIterator<Item>::CurrentItem () const { if (IsDone()) { throw IteratorOutOfBounds; return _list->get(_current); implementation First Next IsDone CurrentItem 13

Iterator: Sample Code (4) Using the iterators void PrintEmployees (Iterator<Employee*>& i) { for (i.first();!i.isdone(); i.next()) { i.currentitem()->print(); List<Employee*>* employees; //... ListIterator<Employee*> forward(employees); ReverseListIterator<Employee*> backward(employees); PrintEmployees(forward); PrintEmployees(backward); Iterator: Sample Code (5) SkipList<Employee*>* employees; //... SkipList is a subclass of List SkipListIterator<Employee*> iterator(employees); PrintEmployees(iterator); Avoiding commitment to a specific list implementation class AbstractList { public: virtual Iterator<Item>* CreateIterator() const = 0; //... ; Iterator<Item>* List<Item>::CreateIterator () const { return new ListIterator<Item>(this); // we know only that we have an AbstractList AbstractList<Employee*>* employees; //... Iterator<Employee*>* iterator = employees->createiterator(); PrintEmployees(*iterator); delete iterator; 14

Iterator: Sample Code (6) Making sure iterators get deleted class IteratorPtr { public: IteratorPtr(Iterator<Item>* i): _i(i) { ~IteratorPtr() { delete _i; Iterator<Item>* operator->() { return _i; Iterator<Item>& operator*() { return *_i; private: // disallow copy and assignment to avoid // multiple deletions of _i: IteratorPtr(const IteratorPtr&); IteratorPtr& operator=(const IteratorPtr&); private: Iterator<Item>* _i; ; acts as a proxy IteratorPtr can be treated just like a pointer to an iterator AbstractList<Employee*>* employees; //... Allocated in stack IteratorPtr<Employee*> iterator(employees->createiterator()); PrintEmployees(*iterator); Iterator: Sample Code (7) How to parameterize the iterator with the operation we want to perform on each element Pass in a pointer to a function (global or static) the iterator calls the operation passed to it at each iteration Rely on subclassing (of each traversal) the iterator calls an operation that a subclass overrides An internal ListIterator class ListTraverser { public: ListTraverser(List<Item>* alist); bool Traverse(); protected: virtual bool ProcessItem(const Item&) = 0; private: ListIterator<Item> _iterator; ; 15

Iterator: Sample Code (8) ListTraverser<Item>::ListTraverser ( List<Item>* alist ) : _iterator(alist) { bool ListTraverser<Item>::Traverse () { bool result = false; for ( _iterator.first();!_iterator.isdone(); _iterator.next() ) { result = ProcessItem(_iterator.CurrentItem()); if (result == false) { break; return result; Iterator: Sample Code (9) 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(); The client doesn't specify the iteration loop. The entire iteration logic can be reused 16

Iterator: Sample Code (10) ListIterator<Employee*> i(employees); int count = 0; for (i.first();!i.isdone(); i.next()) { count++; i.currentitem()->print(); if (count >= 10) { break; 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; ; Using External Iterator Internal iterators can encapsulate different kinds of iteration Iterator: Sample Code (11) void FilteringListTraverser<Item>::Traverse () { bool result = false; for ( _iterator.first();!_iterator.isdone(); _iterator.next() ) { if (TestItem(_iterator.CurrentItem())) { result = ProcessItem(_iterator.CurrentItem()); if (result == false) { break; return result; Subclasses override TestItem to specify the test 17

Iterator: Related patterns Composite Iterators are often applied to recursive structures such as Composites Factory Method Polymorphic iterators rely on factory methods to instantiate the appropriate Iterator Memento is often used in conjunction with the Iterator pattern. An iterator can use a memento to capture the state of an iteration. The iterator stores the memento internally 18