iterator behavioural design pattern

Post on 09-Jan-2016

30 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

Iterator behavioural design pattern. Eivind J. Nordby University of Karlstad Inst. for Information Technology Dept. of Computer Science Last revised 051010. Introduction. An iterator can be used in order to - PowerPoint PPT Presentation

TRANSCRIPT

Iterator behavioural design Iterator behavioural design patternpattern

Eivind J. Nordby

University of Karlstad

Inst. for Information Technology

Dept. of Computer ScienceLast revised 051010

1998-09-15 Computer Science, University of

Karlstad2

Introduction Introduction

An iterator can be used in order to provide a way to access the elements of an

aggregate object sequentially without exposing its underlying representation

always used with ”containers” or ”collections”

1998-09-15 Computer Science, University of

Karlstad3

next()

The basic ideaThe basic idea

aContainer

anElement

anElement

anElement

anElement

anElement

anElement

aContainerIterator

+first()

+next()

+isDone()

+current()

current-Element*

”on” or “over”

isDone()

first()

current()

1998-09-15 Computer Science, University of

Karlstad4

Basic usageBasic usage

List* pMyList = new List;// populate the listListIterator *pli = new ListIterator(pMyList);

// Implicit or explicit: pli->first();while (!pli->isDone()) {

// do something with pli->current(); pli->next();}delete pli;

1998-09-15 Computer Science, University of

Karlstad5

Abstract iteratorsAbstract iterators

1998-09-15 Computer Science, University of

Karlstad6

Iterators: ConsequencesIterators: Consequences

They support variations in the traversal of an aggregate.– through polymorphic iteration

They simplify the Aggregate interface.– remove the iterator interface from aggregate

More than one traversal can be pending on an aggregate.

1998-09-15 Computer Science, University of

Karlstad7

Iterate Through the Positions of a Iterate Through the Positions of a Game BoardGame Board

low …

high…

… … … … … …

pci

pri

1998-09-15 Computer Science, University of

Karlstad8

MotivationsMotivations

Why positions and not fields?– Does not assume that there is a field

Use the iterator to populate the board with fields Use the iterator to print the fields

Why separate for columns and rows?– Allows to express explicitly the intention of the

iteration For instance row-wise printing Without knowing the implementation

Why a common base class (BoardIterator)– Same protocol for all iterators

1998-09-15 Computer Science, University of

Karlstad9

Example ClientExample Client

// <select a game, suppressed>

Board* myBoard;

myBoard = GameFactory::instance().createBoard();

// print the board row by row by

// iterating over the positions of the first column

BoardIterator *pci = myBoard->columnIterator();

while (!pci->isDone()) {

// do something at pci->current(), see next slide

pci->next(); // go on to the next game row

}

delete pci;

1998-09-15 Computer Science, University of

Karlstad10

do something with pci->current()do something with pci->current()

// iterate three times over the current row positions

const int drawRows = 3; // for each position

for (int i = 1; i <= drawRows; i++) {

BoardIterator *pri = myBoard->rowIterator(pci->current());

while (!pri->isDone()) {

out << myBoard->fieldAt(pri->current())->toString(i);

pri->next();

}

delete pri;

} OO style: create a new iterator object whenever needed rather than reusing the same

one– Simplifies logic and improves correctness

1998-09-15 Computer Science, University of

Karlstad11

Graphic alternativeGraphic alternative

For a graphic clientvoid paint(GraphicContext* gc){ Board* myBoard; myBoard = GameFactory::instance().createBoard(); myBoard->paint(gc); // iterating over the positions of the board BoardIterator *pbi = myBoard->defaultIterator(); while (!pbi->isDone()) { myBoard->fieldAt(pbi->current())->paint(gc); pbi->next(); } delete pci;} // paint

1998-09-15 Computer Science, University of

Karlstad12

A more realistic graphic wayA more realistic graphic way

In the previous example, each field needs to compute its own position on the graphic surface.

Normally, the graphic picture will consist of a lot of small views, one for each field– The board view paints the board frame– Each field view paints its field and piece– The paiting is inisialized from the operating system– No iterator is needed at all

1998-09-15 Computer Science, University of

Karlstad13

A more realistic graphic clientA more realistic graphic client

class BoardView{ Board* board; // assigned on creation void paint() {board->paint(this->graphicContext();}} // class BoarViewclass FieldView{ Field* field; void paint() { gc->foregroundColor(fgcOf(field->position()); gc->backgroundColor(bgcOf(field-’>position()); gc->inset(Point(1,1)); field->paint(this->graphicContext(); }

1998-09-15 Computer Science, University of

Karlstad14

A graphics aware modelA graphics aware model

class Field{

Piece* piece;

void paint(GraphicContext* gc){

if (piece!=0) piece->paint(gc);

gc->drawSquare(Point(0,0), gc->size());

}

} // class Field

class Piece{

Bitmap bitMap; // initialized at creation

void paint(GraphicContext* gc){gc->draw(bitMap);}

}

1998-09-15 Computer Science, University of

Karlstad15

ColumnIteratorColumnIterator

Iterate over the positions of a column– Defaults to the first column on the board– ColumnIterator(Board* board);

Alternative constructor for explicit start position– Iterate over a column starting from a given

position– ColumnIterator(Board* board, Point position);

1998-09-15 Computer Science, University of

Karlstad16

ColumnIterator FeaturesColumnIterator Features Constructors

– ColumnIterator(Board* board) // Pre: board not null

– ColumnIterator(Board* b, Point pos) // Pre: b not null

Accessors– Point current() // Post: result = current position

– bool isDone() // Post: result = current not inside board

Transformers– void next() // Post: current stepped to next position

1998-09-15 Computer Science, University of

Karlstad17

Abstract BoardIteratorAbstract BoardIterator RowIterator and ColumnIterator share

– the same protocol– the same constructors– the same implementation

except for the function next()

They are obvious candidates to share– a common (abstract/default) base class– the derived classes (re)define next()

Some ideas follow

1998-09-15 Computer Science, University of

Karlstad18

Conceptual ModelConceptual Model

positions

*

+current1

* 1

iterates over

Board

+fieldAt:Field+contains:bool+low:Point+high:Point+size:Point

RowIterator

+next:void

PointColumnIterator

+next:void

BoardIterator

+isDone:bool+next:void

1998-09-15 Computer Science, University of

Karlstad19

A Possible ImplementationA Possible Implementation

Assume the following Access methods for Board:

– Field* fieldAt(Point position);– Point low(); // lowest position– Point high(); // highest position– Point size(); // dimensions– bool contains(Point position);

Access methods for Field:– Point position();– Board *board();

1998-09-15 Computer Science, University of

Karlstad20

Design modelDesign model

_high

1

_low

1

_board

1

_current!

0..1

_position

_board

*0..1

ColumnIterator

+next:void

RowIterator

+next:void

Point

+x:int+y:int+incX:void+incY:void+setX:void+setY:void

Board

+fieldAt:Field+contains:bool+low:Point+high:Point+size:Point

BoardIterator

+isDone:bool+current:Point+next:void

Field

+toString:String

1998-09-15 Computer Science, University of

Karlstad21

class BoardIteratorclass BoardIterator Private instance variables

Point _current; // the current posBoard* _pBoard; // != null

Implementation invariant– _current.x() is fixed, identifies the

column– _current.y() is the current row number– *_pBoard is the board iterated over

Constructor(Board *board) // board != nullBoardIterator(Board *board) { _current = board->low(); _pBoard = board}

1998-09-15 Computer Science, University of

Karlstad22

class BoardIterator (cont’d)class BoardIterator (cont’d)

Public iterator access functions// void first() {_current.setY(board->low().y());}void next() {<move to next in some default order>}boolean isDone() {return !inside(_current);}Point current() {return _current;}

private:bool inside(Point position){

return board->contains(position);}

None of the operations need a precondition– Precondition !isDone() only needed when actually

accessing a position on a board– Responsibility may be delegated to the client

1998-09-15 Computer Science, University of

Karlstad23

class ColumnIteratorclass ColumnIterator Inherits BoardIterator Implementation invariant

– current().x() fixed, identifies the column– current().y() is the current row number

Constructor(Board *board) // board != nullColumnIterator(Board *board): BoardIterator(board) {}

Redefined operationvoid next() {current().incY();}

1998-09-15 Computer Science, University of

Karlstad24

RowIteratorRowIterator

Very similar to ColumnIterator– same instance variables as ColumnIterator– iterating over the positions of a row, not those

of a column In this example I show another constructor

– Taking a specific position as an argument– Iterate over a row starting from the position

1998-09-15 Computer Science, University of

Karlstad25

class RowIteratorclass RowIterator

Public constructorsBoardIterator(Board *pb, Point start) {

_current = start; _pBoard = pb;}...RowIterator(Board *pb, Point start): BoardIterator(pb, start) {}

Redefined access function– void next() {current().incX();}

top related