NET design mode the second branch-mode (17): Iterator mode (Iterator pattern)

Source: Internet
Author: User

Overview

In object-oriented software design, we often encounter a class of collection objects, the internal structure of such a collection object may have a variety of implementations, but it comes down to two points that we need to care about: one is the data storage structure inside the collection, and the second is to traverse the data inside the collection. One of the principles of object-oriented design is the single responsibility principle of a class, so we need to break down these responsibilities as much as possible, and use different classes to take on different responsibilities. The iterator pattern is the separation of the traversal behavior of the collection object and the abstraction of an iterator class to be responsible for not exposing the internal structure of the collection, but also allowing the external code to transparently access the data inside the collection.

Intention

Provides a way to sequentially access individual elements of an aggregated object without exposing the object's internal representation. [GOF "design mode"]

Structure diagram

The iterator pattern structure is as follows:

Figure 1 Iterator Pattern structure diagram

Examples of life

Iterators provide a way to sequentially access individual elements in a collection object without exposing an internal representation of the object. In the early days of television, a dial was used to change the channel. When changing the channel, you need to manually rotate the dial to move through each channel, regardless of whether the channel has a signal. Now the TV, use [next] and [previous] button. When the [next] button is pressed, it switches to the next preset channel. Imagine watching TV in a hotel in a strange city. When changing the channel, it is not the channel that matters, but the content of the program. If you're not interested in a channel's program, you can change the channel instead of knowing it's a few channels.

Figure 2 Iterator Mode object graph using the frequency selector as an example

Iterator Mode Commentary

In object-oriented software design, we often encounter a class of collection objects, the internal structure of such a collection object may have a variety of implementations, but it comes down to two points that we need to care about: one is the data storage structure inside the collection, and the second is to traverse the data inside the collection. One of the principles of object-oriented design is the single responsibility principle of a class, so we need to break down these responsibilities as much as possible, and use different classes to take on different responsibilities. The iterator pattern is the separation of the traversal behavior of the collection object and the abstraction of an iterator class to be responsible for not exposing the internal structure of the collection, but also allowing the external code to transparently access the data inside the collection. Here is a simple schematic example, the class structure diagram is as follows:

Figure 3 Sample code structure diagram

First there is an abstract aggregation, the so-called aggregation is the collection of data, you can iterate to access it. It has only one method Getiterator () lets subclasses implement to obtain an iterator object.

// <summary> /// Abstract Aggregation /// </summary>  Public Interface ilist{    iiterator getiterator ();}

An abstract iterator, which is used to access the clustered class, encapsulates a number of methods used to read the data in the cluster sequentially. There are usually MoveNext (),CurrentItem (),fisrt (),Next () and other methods to enable subclasses to implement.

/// <summary> /// Abstract iterators /// </summary>  Public Interface iiterator{    bool  MoveNext ();    Object CurrentItem ();     void First ();     void Next ();}

Specific aggregation, which implements the only method in the abstract aggregation, while preserving a set of data, here we add the length property and getelement () method is to facilitate access to the data in the aggregation.

/// <summary>///Specific Aggregation/// </summary> Public classconcretelist:ilist{int[] list;  Publicconcretelist () {list=New int[] {1,2,3,4,5}; }     Publiciiterator Getiterator () {return NewConcreteiterator ( This); }     Public intLength {Get{returnlist. Length; }    }     Public intGetElement (intindex) {        returnList[index]; }}

The concrete iterator implements the four methods in the abstract iterator, in which the constructor needs to accept the parameters of a specific aggregation type, where we can write different iterations according to the actual situation.

/// <summary>///Specific iterators/// </summary> Public classconcreteiterator:iiterator{Privateconcretelist list; Private intindex;  Publicconcreteiterator (concretelist list) { This. List =list; Index=0; }     Public BOOLMoveNext () {if(Index <list. Length)return true; Else            return false; }     PublicObject CurrentItem () {returnlist.    GetElement (index); }     Public voidFirst () {index=0; }     Public voidNext () {if(Index <list. Length) {Index++; }    }}

Simple client-side program invocation:

/// <summary>///Client Programs/// </summary>classprogram{Static voidMain (string[] args)        {Iiterator iterator; IList List=Newconcretelist (); Iterator=list.        Getiterator ();  while(iterator. MoveNext ()) {inti = (int) iterator.            CurrentItem ();            Console.WriteLine (i.ToString ()); Iterator.        Next ();    } console.read (); }}

A simple iterator example is over, and here we are not using anything. NET feature, in C #, implementing the iterator pattern has no need to be so troublesome, already there are some specific implementations of the C # language itself, as the following will say.

. NET iterator mode in the

Implementing the iterator pattern under. NET, already exists for the aggregation interface and iterator interfaces, where IEnumerator is the role of the iterator, which is implemented as follows:

 Public Interface ieumerator{    object  current    {        get;    }     BOOL MoveNext ();     void Reset ();}

The Reset () method returns the value of the element in the current collection, the MoveNext () method reverts to the position, and true indicates that the iterator successfully advances to the next element in the collection, and the return value of FALSE indicates that it is already at the end of the collection. A collection object capable of providing element traversal, with the IEnumerator interface implemented in. NET.

IEnumerable is the role of abstract aggregation, there is only one GetEnumerator () method, if the collection object needs to have the ability to traverse, it must implement the interface.

 Public Interface ienumerable{    ieumerator GetEnumerator ();}

Here's a look at . Example of an iterator under NET1.1, the personclass is an enumerable class. the Personsenumerator class is an enumerator class. This example comes from http://www.theserverside.net/, which I have simply transformed.

 Public classpersons:ienumerable { Public string[] m_names;  PublicPersons (params string[] Names) {M_names=New string[Names.length]; Names.copyto (M_names,0); }     Private string  This[intIndex] {         Get         {             returnM_names[index]; }         Set{M_names[index]=value; }     }     PublicIEnumerator GetEnumerator () {return NewPersonsenumerator ( This); }} Public classpersonsenumerator:ienumerator{Private intindex =-1; PrivatePersons P;  Publicpersonsenumerator (Persons P) { This. P =P; }     Public BOOLMoveNext () {index++; returnIndex <p.m_names.length; }     Public voidReset () {index= -1; }     Public ObjectCurrent {Get        {            returnP.m_names[index]; }    }} 

Look at the call to the client code:

classProgram {Static voidMain (string[] args) {Persons arrpersons=NewPersons ("Michel","Christine","Mathieu","Julien"); foreach(stringSincharrpersons)         {Console.WriteLine (s);     } console.readline (); } }

The program will output:

Michel Christine Mathieu Julien

Now that we're analyzing what the compiler does when it executes the foreach statement, it executes the code roughly as follows:

classProgram {Static voidMain (string[] args) {Persons arrpersons=NewPersons ("Michel","Christine","Mathieu","Julien"); IEnumerator e=Arrpersons.getenumerator ();  while(E.movenext ()) {Console.WriteLine (string) e.current);    } console.readline (); } }

You can see that this code is very similar to the example code we mentioned earlier. And in this case, we spend most of our energies on implementing iterators and iterative classes, in . NET2.0 below, thanks to the yield return keyword, the implementation will be more simple and elegant. Now let's re-implement the example in 2.0:

 Public classpersons:ienumerable {string[] m_names;  PublicPersons (params string[] Names) {M_names=New string[Names.length]; Names.copyto (M_names,0); }      PublicIEnumerator GetEnumerator () {foreach(stringSinchm_names) {             yield returns; }     } } classProgram {Static voidMain (string[] args) {Persons arrpersons=NewPersons ("Michel","Christine","Mathieu","Julien"); foreach(stringSincharrpersons)         {Console.WriteLine (s);     } console.readline (); } }

The program will output:

Michel Christine Mathieu Julien

The same functionality is achieved with the yield return keyword, which makes it very simple. All right, about. NET in the iterator model is said so much, more detailed content you can refer to the relevant information.

Effect and key points of realization

1. Iterative abstraction: Accesses the contents of an aggregated object without exposing its internal representation.

2. Iterative polymorphism: Provides a unified interface for traversing different collection structures, enabling the same algorithm to operate on different sets of structures.

3. The robustness of an iterator is considered: traversing the same time as changing the collection structure where the iterator is located can cause problems.

Applicability

1. Accesses the contents of an aggregated object without exposing its internal representation.

2. Supports multiple traversal of an aggregated object.

3. Provides a unified interface for traversing different aggregation structures (that is, support for polymorphic iterations).

Summarize

The iterator pattern is the separation of the traversal behavior of the collection object and the abstraction of an iterator class to be responsible for not exposing the internal structure of the collection, but also allowing the external code to transparently access the data inside the collection.

Resources

Erich Gamma, etc., "design mode: The basis of reusable object-oriented software", Mechanical industry Press

Robert C.martin, "Agile Software Development: principles, patterns and practices", Tsinghua University Press

Shanhong, Java and patterns, electronic industry publishing house

Alan Shalloway James R. Trott, "Design Patterns explained", China Power Press

MSDN Webcast "C # Object-oriented design pattern discussion on: Iterator iterator mode (behavioral mode)"

NET design mode the second branch-mode (17): Iterator mode (Iterator pattern)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.