Ubiquitous Iterator
This Article is contributed by Wang Hailong.
Preface
As one of 23 basic Design Patterns, Iterator seems to appear everywhere. This article discusses some scenarios where Iterator Pattern is applied, including STL, Collection in Java, IEnumXXXX interface in COM, IRowset interface in OLE DB, RecordSet Object in
ADO
, RESURSET IN JDBC, CURSOR in Oracle's SQL / PL.
Iterator Concept
Iterator Pattern Separates The orthization Operation from Container / Collection. To Satisfy Iterator Pattern, There Must Be Two Objects: a Container and ITS Iterator.
THE AIFY The WAY OF ITERATING A Container, in Spite of What Kiand Of Data IS Put in The Container, And How The Container's Internal Structure iswares.
The Following Is A Simple Example Imitation STL.
// SimpleArray.cpp
Template
Class SimpleArray
{
T Data [100];
PUBLIC:
Class Iterator
{
SimpleArray
INT M_ICURRENDEX;
Friend Class SimpleArray
PUBLIC:
ITerator (SimpleArray
{
}
Void reset ()
{
m_ICURRENDEX = 0;
}
T Operator * ()
{
Return M_Parray-> Data [m_icurrentIndex];
}
Void Operator - ()
{
m_ICURRENTINDEX -;
}
Void Operator ()
{
M_ICURRENTINDEX ;
}
Bool Operator! = (const itrator & another)
{
IF (m_parray! = another.m_parray)
Return True;
IF (m_ICURRENTINDEX! = another.m_ICURRENDEX)
Return True;
Return False;
}
}
Iterator begin ()
{
Iterator it (this);
IT.m_ICurrentIndex = 0;
Return IT;
}
Iterator end ()
{
Iterator it (this);
IT.m_ICurrentIndex = 100;
Return IT;
}
Friend class iterator;
}
Template
{
Container :: Iterator IT;
INT TOTAL = 0;
For (it = con.begin (); it! = con.nd (); it )
{
Total = * IT;
}
Return Total;
}
Void test ()
{
SimpleArray
Int total = sum (con);
}
If Later We don't want to use the SimpleArray Any More, We can change the test function as bevel.
#include
Void test ()
{
Set
Int total = sum (con);
}
Hence The Separation of Data Structure and Algorithm.
STL
......................... ..
As We Have Seen, Algorithms CAN EXIST Independent of Data Structure Using Stl. The key concept IS "Function Object", Which is detailed in chapter 21 "STL Algorithms" of << Thinking In C >>.
Now Lets Take A Glimpse of What Is A "Function Object".
Take The Method "Sort" of list in stl, for example.
Template
The Parameter Pr inherits The "Function Object" Greater and is Also A "Function Object".
And The Implementation Likey Takes The Following Shape.
Struct CComparetwoItem: Public Std :: Greater
{
PUBLIC:
Bool Operator () (T Item1, T Item2)
{
}
}
Iterator in Java and C
ENUMERATION INTERFACE AND ITERATOR Interface (in java2) Are Self-Explanatory. What is more, Sub View Is Supported in Java.
Similar Effect Can Be Approximated Through Filter Iterator.
Ienumxxxx Interface In COM
The Definition of Ienumxxxx IS:
Interface IEnumxxx: IUNKNOWN
{
Virtual HRESULT NEXT (UNSIGNED Long Celt, xxxx * rgelt, unsigned long * pCeltfetched) = 0; Virtual HRESULT SKIP (unsigned long celt) = 0;
Virtual hResult reset () = 0;
Virtual HRESULT Clone (IEnumxxxx ** PPEUnm);
}
An Good Example IS "Connectable Objects" in COM.
Interface IconnectionPoint: IUNKNOWN
{
HRESULT GETCONNECTIONINTERFACE (IID * PIID);
HRESULT GETCONNECTIONPOINTCONTAINER (iconnectionPointContainer ** PPCPC);
HRESULT Advise (IUNKNOWN * PUNK, DWORD * PDWCOOKIE);
HRESULT UNADVISE (DWORD DWCOOKIE);
HRESULT EnumConnections (IEnumConnections ** Ppenum);
}
Interface iconnectionPointContainer: iUnknown
{
HRESULT ENUMCONNECTIONPOINTS (IEnumConnectionPoints ** ppenum);
HRESULT FINDCONNECTIONPOINT (REFIID RIID, ICONNECTIONPOINT ** PPCP);
}
Interface IenumConnectionPoints
{
HRESULT NEXT (Ulong Cconnections, IconnectionPoint ** RGPCN, ULONG * PCFETCHED);
HRESULT SKIP (Ulong Cconnections);
HRESULT RESET (VOID);
HRESULT Clone (IEnumConnectionPoints ** Ppenum);
}
IConnectionPointContainer holds IConnectionPoint and IConnectionPointContainer's method EnumConnectionPoints returns an IEnumConnectionPoints which can iterate the IConnectionPointContainer to get every IConnectionPoint.
Irowset Interface In Ole DB
Irowset Method Description:
AddREFROWS ADS A Reference Count To An EXISTING ROW HANDLE.
GetData Retrieves Data from The Rowset's Copy of The Row.
GetNextrol Fetches Rows Sequentially, Remembering The Previous Position.
ReleaseRows Releases Rows.
RestartPosition Repositions the next fetch position; thing is, its position when the rowset is first create.
The definition of iCommand :: EXCUTE IS:
HRESULT Execute (IUnknown * pUnkOuter, REFIID riid, DBPARAMS * pParams, LONG * pcRowsAffected, IUnknown ** ppRowset); This method returns an IRowset interface which can iterate through the result of "Excute".
Recordset Object in
ADO
The Follow Text Is Extracted from
ADO
Help.
A Recordset object represents the entire set of records from a base table or the results of an executed command. At any time, the Recordset object only refers to a single record within the set as the current record.
Using the open method ON A Recordset Object Opens A CURSOR THAT RECORDS from a base table or the results of a query.
Ways to get recordset Object Include:
ON A Command Object: Set Recordset = Command.execute (Recordsaffected, Parameters, Options)
ON A Connection Object: Set Recordset = Connection.execute (CommandText, Recordsaffected, Options)
Resultset in JDBC
Connection con = GetConnection ();
Statement Stmt = con.createstatement (ResultSet.Type_Scrool_INSENTIVE,
ResultSet.concur_read_only);
ResultSet RS = Stmt.excuteQuery (Query);
While (rs.next ()) {c};
Cursor in Oracle's SQL / PL
We can Look on Cursor as a forward-only iterator.
Appendix
Some Great Books About Design Patterns:
<< Design Patterns >> by
Zurich
,
Sydney
,
Urbana
,
Hawthorne
;
<< Thinking in C >> and << Thinking in java >> by bruce eckel;
<< The Design Pattern Java Companion >> by James W. Cooper.