Iterátor (tervezési minta)

Az oldal jelenlegi verzióját még nem ellenőrizték tapasztalt közreműködők, és jelentősen eltérhet a 2016. május 9-én felülvizsgált verziótól ; az ellenőrzések 9 szerkesztést igényelnek .
iterátor
Iterátor
Típusú viselkedési
Leírása: Tervezési minták Igen

Az Iterátor  egy viselkedési tervezési minta . Olyan objektumot jelöl, amely szekvenciális hozzáférést tesz lehetővé egy összesített objektum elemeihez anélkül, hogy az egyes összesített objektumok leírását használná.

Például az olyan elemek, mint a fa , egy linkelt lista , egy hash tábla és egy tömb bejárhatók (és módosíthatók) egy Iterator objektum segítségével .

Az elemeken keresztüli iterációt az iterátor objektum végzi, nem maga a gyűjtemény. Ez leegyszerűsíti a gyűjtemény felületét és megvalósítását, és elősegíti a problémák logikusabb elkülönítését .

A teljesen megvalósított iterátor jellemzője, hogy az iterátort használó kód nem tudhat semmit az iterált aggregátum típusáról.

Természetesen (C++-ban) szinte minden aggregátum megismételhető void* mutatóval, de:

Az iterátorok lehetővé teszik egy aggregátum típusának és terminátorának absztrahálását a polimorf Next (C++-ban gyakran operátorként++) és a polimorf aggregate.end() segítségével, amely az "összesítés vége"-t adja vissza.

Így lehetővé válik az iterátorok tartományaival való munka, az iterált aggregátum típusának ismerete hiányában. Például:

Iterátor itBegin = aggregate . kezdődik (); Iterátor itEnd = aggregátum . vége (); func ( itBegin , itEnd );

És tovább:

void func ( Iterator itBegin , Iterator itEnd ) { for ( Iterator it = itBegin , it != itEnd ; ++ it ) { } }

Példák

C#

Forrásszöveg C# nyelven /* mintakód C#-ban Ez a szerkezeti kód az Iterátor mintát mutatja be, amely lehetőséget biztosít a tételek gyűjteményének áthaladására (iterációra) anélkül, hogy részletezné a gyűjtemény mögöttes szerkezetét. */ kód elrejtése // Iterátor minta -- Szerkezeti példa a rendszer használatával ; a System.Collections használatával ; névtér DoFactory.GangOfFour.Iterator.Structural { /// <summary> /// MainApp indítási osztály a Structural számára /// Iterátor tervezési minta. /// </summary> class MainApp { /// <summary> /// Belépési pont a konzolalkalmazásba. /// </summary> static void Main () { ConcreteAggregate a = new ConcreteAggregate (); a [ 0 ] = "A tétel" ; a [ 1 ] = "B tétel" ; a [ 2 ] = "C tétel" ; a [ 3 ] = "D tétel" ; // Iterátor létrehozása és összesített ConcreteIterator megadása i = new ConcreteIterator ( a ); Konzol . WriteLine ( "Iteráció a gyűjtemény felett:" ); tárgyelem = i . _ első (); while (! i . IsDone ()) { Konzol . WriteLine ( elem ); item = i . következő (); } // Várja meg a felhasználói konzolt . ReadKey (); } } /// <summary> /// Az 'Aggregate' abstract class /// </summary> abstract class Aggregate { public abstract Iterator CreateIterator (); public abstract int Szám { get ; védett készlet ; } public absztrakt objektum this [ int index ] { get ; készlet ; } } /// <summary> /// A 'ConcreteAggregate' osztály /// </summary> class ConcreteAggregate : Aggregate { private readonly ArrayList _items = new ArrayList (); public override Iterator CreateIterator () { return new ConcreteIterator ( this ); } // Lekéri a cikkszámot public override int Szám { get { return _items . gróf ; } védett készlet { } } // Indexelő nyilvános felülbíráló objektum this [ int index ] { get { return _items [ index ]; } set { _items . beszúr ( index , érték ); } } } /// <summary> /// Az 'Iterátor' abstract class /// </summary> abstract class Iterátor { public abstract object Először (); publikus absztrakt objektum Következő (); public abstract bool IsDone (); nyilvános absztrakt objektum CurrentItem (); } /// <summary> /// A 'ConcreteIterator' osztály /// </summary> class ConcreteIterator : Iterator { private readonly Aggregate _aggregate ; private int _current ; // Constructor public ConcreteIterator ( Aggregate aggregate ) { this . _aggregate = összesítés ; } // Lekéri az első iterációs elemet public override object First () { return _aggregate [ 0 ]; } // Lekéri a következő iterációs elemet public override object Next () { object ret = null ; _current ++; if ( _aktuális < _összesítő . Szám ) { ret = _aggregate [ _current ]; } return ret ; } // Lekéri az aktuális iterációs elemet public override object CurrentItem () { return _aggregate [ _current ]; } // Lekérdezi, hogy az iterációk teljesek-e nyilvános felülírás bool IsDone () { return _current >= _aggregate . gróf ; } } } Kimenet Iterálás a gyűjtemény felett : A tétel B tétel C tétel D

PHP5

PHP5 forráskód /** * Az iterátor minta mechanizmust biztosít a gyűjtemény elemei közötti iterációhoz anélkül, hogy felfedné a gyűjtemény megvalósítását. * * Az elemeken keresztüli iterációt az iterátor objektum végzi, nem maga a gyűjtemény. * Ez leegyszerűsíti a gyűjtemény felületét és megvalósítását, valamint hozzájárul a felelősségek logikusabb elosztásához. */ namespace iterator1 { /** * A közös interfész kényelmes a kliens számára, mivel a kliens le van választva az objektumok gyűjteményének megvalósításáról. * * A ConcreteAggregate objektumok gyűjteményét tartalmazza, és olyan metódust valósít meg, amely egy iterátort ad vissza ehhez a gyűjteményhez. */ interface IAggregate { /** * Minden ConcreteAggregate íz felelős egy Concrete Iterator példány létrehozásáért, amely * használható az objektumok gyűjteményén keresztüli iterációra. */ nyilvános függvény createIterator (); } /** * Az Iterátor felületet minden iterátornak implementálnia kell. * * A ConcreteIterator felelős az aktuális iterációs pozíció kezeléséért. */ interface IIterator { /** * @abstract * @return logikai érték van-e következő elem a gyűjteményben */ public function hasNext (); /** * @abstract * @return kevert next tömbelem */ public function next (); /** * Eltávolítja a gyűjtemény aktuális elemét * @abstract * @return void */ public function remove (); } /** * Az én példámban mindkét gyűjtemény ugyanazt az iterátort használja – egy tömb iterátort. */ class ConcreteAggregate1 megvalósítja az IAggregate-et { /** * @var Item[] $items */ public $items = tömb (); public function __construct () { $this -> items = array ( new Item ( 1 , 2 ), new Item ( 1 , 2 ), new Item ( 1 , 2 ), ); } public function createIterator () { return new ConcreteIterator1 ( $this -> items ); } } class ConcreteAggregate2 megvalósítja az IAggregate-et { /** * @var Item[] $items */ public $items = tömb (); public function __construct () { $this -> items = array ( new Item ( 2 , 3 ), new Item ( 2 , 3 ), new Item ( 2 , 3 ), ); } public function createIterator () { return new ConcreteIterator1 ( $this -> items ); } } class ConcreteIterator1 implementálja az IIteratort { /** * @var Item[] $elemek */ védett $elemek = tömb (); /** * @var int $pozíció tárolja az aktuális iterációs pozíciót a tömbben */ public $position = 0 ; /** * @param $items iterálandó objektumok tömbje */ public function __construct ( $items ) { $this -> items = $items ; } public function hasNext () { if ( $this -> position >= count ( $this -> items ) || count ( $this -> items ) == 0 ) { return ( false ); } else { return ( igaz ); } } public function next () { $menuItem = $this -> items [ $this -> position ]; $this -> pozíció ++ ; return ( $menuItem ); } public function remove () { if ( $this -> position <= 0 ) { throw new \Exception ( 'Nem hívhatod meg az eltávolítást, mielőtt legalább egy next() meghívásra került' ); } if ( $this -> items [ $this -> position - 1 ] != null ) { for ( $i = $this -> position - 1 ; $i < count ( $this -> items ); $i + + ) { $this -> items [ $i ] = $this -> items [ $i + 1 ]; } $this -> items [ count ( $this -> items ) - 1 ] = null ; } } } class Client { /** * @var ConcreteAggregate1 $aggregate1 */ public $aggregate1 ; /** * @var ConcreteAggregate2 $aggregate2 */ public $aggregate2 ; public function __construct ( $aggregate1 , $aggregate2 ) { $this -> aggregate1 = $aggregate1 ; $this -> aggregate2 = $aggregate2 ; } public function printAggregatesItems () { $iterátor1 = $this -> aggregate1 -> createIterator (); echo " \ nElőször" ; $this -> printIteratorItems ( $iterator1 ); $iterátor2 = $this -> aggregate2 -> createIterator (); echo " \n\ nSecond" ; $this -> printIteratorItems ( $iterator2 ); } /** * @param $iterator IIterator */ private function printIteratorItems ( $iterator ) { while ( $iterator -> hasNext ()) { $item = $iterator -> next (); echo " \n $cikk->név $cikk->ár $cikk->leírás " ; } } } class Item { public $price ; nyilvános $név ; nyilvános $leírás ; public function __construct ( $név , $ár , $leírás = '' ) { $this -> name = $name ; $ez -> ár = $ár ; $this -> description = $leírás ; } } $futó = új ügyfél ( new ConcreteAggregate1 (), new ConcreteAggregate2 ()); $futó -> printAggregatesItems (); }

PHP5 builder iterator példa

PHP5 builder iterator forráskód /** * Composer minta külső iterátorral * Az iterátor rekurziót használ az elemek fán való iterációhoz */ namespace compositeIterator { /** * A kliens az AComponent felületet használja az objektumokkal való munkavégzéshez. * Az AComponent interfész az összes komponens interfészt határozza meg: mind a kombinációk, mind a levél csomópontok számára. * Az AComponent alapértelmezett viselkedést valósíthat meg az add() remove() getChild() és egyéb műveleteknél */ abstract class AComponent { nyilvános $customPropertyName ; nyilvános $customPropertyDescription ; /** * @param AComponent $komponens */ public function add ( $komponens ) { throw new \Exception ( "Nem támogatott művelet" ); } /** * @param AComponent $komponens */ public function remove ( $komponens ) { throw new \Exception ( "Nem támogatott művelet" ); } /** * @param int $int */ public function getChild ( $int ) { throw new \Exception ( "Nem támogatott művelet" ); } /** * @return IPhpLikeIterator */ absztrakt függvény createIterator (); public function operation1 () { throw new \Exception ( "Nem támogatott művelet" ); } } /** * A Leaf örökli az add() remove() getChild( metódusokat, aminek nem biztos, hogy értelme van egy levélcsomópont esetén. * Bár a levélcsomópontot nulla gyermekes csomópontnak tekinthetjük * * A Leaf határozza meg a Ehhez a Composite interface által támogatott műveleteket valósítja meg */ class Leaf extends AComponent { public function __construct ( $name , $description = '' ) { $this -> customPropertyName = $name ; $this -> customPropertyDescription = $leírás ; } public function createIterator () { return new NullIterator (); } public function operation1 () { echo ( " \n Level vagyok { $this -> customPropertyName } , nem akarom elvégezni az 1. műveletet. { $this -> customPropertyDescription } " ); } } class NullIterator implementálja az IPhpLikeIterator { public function valid () { return ( false ); } public function next () { return ( false ); } public function current () { return ( null ); } public function remove () { throw new \CEexception ( 'nem támogatott művelet' ); } } /** * A Composite felület meghatározza azon összetevők viselkedését, amelyeknek gyermekei vannak, és tárhelyet biztosít számukra. * * A Composite Leaf-specifikus műveleteket is megvalósít. Némelyikük nem ismeri a kombinációk értelmét; ilyen esetekben kivételt dobnak. */ class Composite kiterjeszti AComponent { private $_iterator = null ; /** * @var \ArrayObject AComponent[] $összetevők az AComponent típusú gyermek tárolására */ public $components = null ; public function __construct ( $name , $description = '' ) { $this -> customPropertyName = $name ; $this -> customPropertyDescription = $leírás ; } /** * @param AComponent $komponens */ public function add ( $komponens ) { if ( is_null ( $this -> komponensek )) { $this -> komponensek = new \ArrayObject ; } $this -> összetevők -> hozzáfűzés ( $komponens ); } public function remove ( $komponens ) { foreach ( $this -> összetevők as $i => $c ) { if ( $c === $komponens ) { unset ( $this -> összetevők [ $i ]); } } } public function getChild ( $int ) { return ( $this -> komponensek [ $int ]); } public function operation1 () { echo " \n\n $this->customPropertyName $this->customPropertyDescription " ; echo " \n --------------------------------" ; $iterátor = $this -> összetevők -> getIterator (); while ( $iterátor -> érvényes ()) { $komponens = $iterátor -> aktuális (); $komponens -> művelet1 (); $iterátor -> következő (); } } /** * @return CompositeIterator */ public function createIterator () { if ( is_null ( $this -> _iterator )) { $this -> _iterator = new CompositeIterator ( $this -> összetevők -> getIterator ()); } return ( $this -> _iterator ); } } /** * Rekurzív kompozit iterátor */ class CompositeIterator implementálja az IPhpLikeIterator { public $verem = tömb (); /** * @param \ArrayIterator $componentsIterator */ public function __construct ( $componentsIterator ) { //$this->stack= new \ArrayObject; $this -> verem [] = $componentsIterator ; } public function remove () { throw new \CEexception ( 'nem támogatott művelet' ); } public function valid () { if ( üres ( $this -> verem )) { return ( false ); } else { /** @var $componentsIterator \ArrayIterator */ // az első elem lekérése $componentsIterator = array_shift ( array_values ​​​​( $this -> verem )); if ( $componentsIterator -> érvényes ()) { return ( igaz ); } else { array_shift ( $this -> verem ); return ( $this -> valid ()); } } } public function next () { /** @var $componentsIterator \ArrayIterator */ $componentsIterator = aktuális ( $this -> verem ); $komponens = $komponensekIterátor -> áram (); if ( $component instanceof Composite ) { array_push ( $this -> verem , $component -> createIterator ()); } $componentsIterator -> next (); //return($komponens); } public function current () { if ( $this -> valid ()) { /** @var $componentsIterator \ArrayIterator */ // az első elem lekérése $componentsIterator = array_shift ( array_values ​​​​( $this -> verem )) ; return ( $componentsIterator -> current ()); } else { return ( null ); } } } /** * Az Iterátor felületet minden iterátornak implementálnia kell. * Ez az interfész a szabványos php iterator interfész része. * Egy adott iterátor felelős egy adott gyűjtemény aktuális iterációs pozíciójának kezeléséért. */ interfész IPhpLikeIterator { /** * @abstract * @return logikai érték az aktuális elem */ érvényes nyilvános függvény (); /** * @abstract * @return vegyes kurzor mozgatása tovább */ public function next (); /** * @abstract * @return mix az aktuális elem lekérése */ public function current (); /** * a gyűjtemény aktuális elemének eltávolítása * @abstract * @return void */ public function remove (); } class Kliens { /** * @varAComponent */ public $topItem ; public function __construct ( $topItem ) { $this -> topItem = $topItem ; } public function printOperation1 () { $this -> topItem -> operation1 (); } public function printOperation2 () { echo " \n\n\n " ; $iterátor = $this -> topItem -> createIterator (); while ( $iterátor -> érvényes ()) { /** @var $komponens AComponent */ $komponens = $iterátor -> aktuális (); if ( strstr ( $component -> customPropertyName , 'leaf1' )) { echo ( " \n Ügyfél vagyok, megtaláltam a következőt: leaf { $component -> customPropertyName } , csak itt hagyom (az első- leafs' tea collection). { $component -> customPropertyDescription } " ); } $iterátor -> következő (); } } } class Teszt { public static function go () { $a = new Összetett ( "c1" ); $b = új kompozit ( "c2" ); $c = új kompozit ( "c3" ); $topItem = new Összetett ( "legfelső elem" ); $topItem -> add ( $a ); $topItem -> add ( $b ); $topItem -> add ( $c ); $a -> add ( new Leaf ( "c1-leaf1" )); $a -> add ( new Leaf ( "c1-leaf2" )); $b -> add ( new Leaf ( "c2-leaf1" )); $b -> add ( new Leaf ( "c2-leaf2" )); $b -> add ( new Leaf ( "c2-leaf3" )); $c -> add ( new Leaf ( "c3-leaf1" )); $c -> add ( new Leaf ( "c3-leaf2" )); $kliens = új kliens ( $topItem ); $kliens -> printOperation1 (); $kliens -> printOperation2 (); } } teszt :: megy (); }

Python

Forráskód Pythonban abc importból ABCMeta , abstractmethod _ osztály iterátor ( metaclass = ABCMeta ): """ Absztrakt iterátor """ _error = Nincs # a hiba osztálya, amely akkor jelenik meg, ha a gyűjtemény határon kívül esik def __init__ ( self , collection , cursor ): """ Konstruktor. :param gyűjtemény: az iterátor által bejárandó gyűjtemény :param cursor: a kurzor kezdeti pozíciója a gyűjteményben (kulcs) """ self ._collection = collection self ._cursor = kurzor @abstractmethod def current ( self ): """ Visszaadja az aktuális elemet, amelyre az iterátor """ lépése mutatott @abstractmethod def next ( self ): """ Mozgassa a kurzort a gyűjtemény következő elemére, és adja vissza """ lépést @abstractmethod def has_next ( self ): """ Ellenőrizze, hogy létezik-e a gyűjtemény következő eleme """ pass @abstractmethod def remove ( self ): """ Távolítsa el a gyűjtemény aktuális elemét, amelyre a kurzor """ lépése mutat def _raise_key_exception ( self ): """ A kurzorban található érvénytelen index emelése """ self self . _error ( 'A(z) {} osztály gyűjteményének nincs kulcsa " {} "' . formátum ( self . __class__ . __name__ , self . _cursor )) osztály ListIterator ( Iterátor ): """ Egy iterátor, amely egy normál listán """ _error = IndexError def __init__ ( self , collection : list ): szuper () . __init__ ( gyűjtemény , 0 ) def current ( self ): ha önmaga . _cursor < len ( self . _collection ): önmagát adja vissza . _gyűjtemény [ én . _cursor ] self . _raise_key_exception () def next ( self ): if len ( self . _collection ) >= self . _kurzor + 1 : saját . _cursor += 1 önmagát adja vissza . _gyűjtemény [ én . _cursor ] self . _raise_key_exception () def has_next ( self ): return len ( self . _collection ) >= self . _kurzor + 1 def remove ( self ): if 0 <= self . _kurzor < len ( self . _collection ): én . _gyűjtemény . eltávolítás ( self . _collection [ self . _cursor ]) else : self . _raise_key_exception () osztály DictIterator ( Iterator ): """ Szótáriterátor - mivel a Python szótárai hash-táblázatként vannak implementálva, a bejárási sorrend a különböző futtatások során változhat """ _error = Kulcshiba def __init__ ( self , collection : dict ): szuper () . __init__ ( gyűjtemény , next ( iter ( gyűjtemény ))) self . _keys = lista ( self . _collection . keys ()) self . _keys . pop ( 0 ) def current ( self ): ha önmaga . _kurzor önmagában . _ _collection : önmagát adja vissza . _gyűjtemény [ én . _cursor ] self . _raise_key_exception () def next ( self ): if len ( self . _keys ): self . _cursor = self . _keys . pop ( 0 ) return self . _gyűjtemény [ én . _cursor ] else : self . _raise_key_exception () def has_next ( self ): return len ( self . _keys ) > 0 def remove ( self ): if self . _kurzor önmagában . _ _gyűjtemény : del self . _gyűjtemény [ én . _cursor ] try : self . következő () kivéve én . _error : raise KeyError ( 'A {} típusú gyűjtemény üres' . formátum ( self . __class__ . __name__ )) else : self . _raise_key_exception () osztály Gyűjtemény ( metaclass = ABCMeta ): """ Absztrakt gyűjtemény """ @abstractmethod def iterator ( self ): át osztály ListCollection ( Gyűjtemény ): """ Burkológyűjtemény egy normál listához """ def __init__ ( self , collection : list ): self . _collection = gyűjtemény def iterator ( self ): return ListIterator ( self . _collection ) osztály DictCollection ( gyűjtemény ): """ Burkológyűjtemény a " " szótárhoz def __init__ ( self , collection : dict ): én . _collection = gyűjtemény def iterator ( self ): return DictIterator ( self . _collection ) def teszt ( cím = str , gyűjtemény = Gyűjtemény ): print ( " \n {} \n " . formátum ( cím )) iterator = gyűjtemény . iterator () print ( iterator . current ()) iterator . next () print ( iterator . next ()) iterator . eltávolítás () print ( iterátor . jelenlegi ()) print ( iterator . has_next ()) print () if __name__ == '__main__' : print ( 'OUTPUT:' ) teszt ( 'Lista tesztelése' , ListCollection ([ 1 , 2 , 3 , 4 , 5 ])) teszt ( 'Szótár tesztelése' , DictCollection ({ 'a') : 1 , 'b' : 2 , 'c' : 3 , 'f' : 8 })) '' KIMENET: Lista tesztelés 1 3 4 Igaz Szótári tesztelés 1 3 2 hamis ''''

Rozsda

Rozsda példa #[származtatás (hibakeresés, klónozás, másolás)] pub struct ExampleRange { kezdés : i64 , áram : i64 , vége : i64 , } impl ExampleRange { pub fn new ( eleje : i64 , vége : i64 ) -> Self { Példatartomány { kezdeni , jelenlegi : kezdődik , vége , } } pub fn iter ( & self ) -> ExampleRange { * önmaga } } használd std :: fmt ; impl fmt :: Az ExampleRange megjelenítése { fn fmt ( & self , f : & mut fmt :: Formátum <' _ > ) -> fmt :: Eredmény { ír! ( f , "{}" , saját . aktuális ) } } impl Iterátor az ExampleRange számára { typeItem = i64 ; _ fn next ( & mut self ) -> Option < Self :: Item > { ha önmaga . jelenlegi < én . vége { ( Egyes ( saját . áram ), saját . áram += 1 ). 0 } más { Egyik sem } } fn last ( mut self ) -> Option < Self :: Item > { ha önmaga . jelenlegi > én . kezdődik { ( self . current -= 1 , Some ( self . current )). egy } más { Egyik sem } } } fn () { let it = PéldaTartomány :: new ( 0 , 6 ); a benne lévő tételhez { println! ( "{}" , elem ); } } '''' KIMENET : 0 egy 2 3 négy 5 ''''