Zurück   Flashforum > Flash > ActionScript > Softwarearchitektur und Entwurfsmuster

Antwort
 
LinkBack Themen-Optionen Ansicht
Alt 07-04-2003, 19:12   #1 (permalink)
helpQLODhelp
 
Benutzerbild von bokel
 
Registriert seit: Feb 2002
Ort: Köln
Beiträge: 8.505
Pattern Iterator

Hier ist mal ein einfaches, aber praktisches Beispiel für die
Vorzüge der OOP. Eine Iterator-Klasse, beispielhaft
für Arrays implementiert.

Theoretisch funktioniert das so, dass jede Klasse mit einer
Liste, die man irgendwie durchlaufen kann, eine Methode
createIterator zur Verfügung stellt. Diese Methode liefert
dann ein Iterator-Object mit der gleichen Schnittstelle wie
unten.
So kann man unabhängig davon, wie die Liste intern
aufgebaut ist, jede Klasse auf die gleiche Weise durchlaufen.

ActionScript:
  1. //---------------------------------------------------------
  2. //**
  3. // Ein normaler Vorwärts-Iterator für Arrays
  4. //*
  5.  
  6. _global.IteratorArray = function(obj){
  7.     this.obj = obj;
  8.     this.actIdx = 0;
  9. };
  10.  
  11. o = IteratorArray.prototype;
  12.  
  13. o.first = function(){
  14.     this.actIdx = 0;
  15. }
  16.  
  17. o.next = function(){
  18.     ++this.actIdx;
  19. }
  20.  
  21. o.isDone = function(){
  22.     return this.actIdx >= this.obj.length;
  23. }
  24.  
  25. o.hasNext = function(){
  26.     return this.actIdx < this.obj.length;
  27. }
  28.  
  29. o.current = function(){
  30.     if(this.isDone()){
  31.         trace("Iterator out of Bounds: " + this.actIdx + ":" + this.obj.length);   
  32.     }
  33.     return this.obj[this.actIdx];
  34. }
  35.  
  36.  
  37. //---------------------------------------------------------
  38. //**
  39. // Ein Rückwärts-Iterator für Arrays
  40. //*
  41.  
  42. _global.IteratorReverseArray = function(obj){
  43.     this.obj = obj;
  44.     this.actIdx = obj.length-1;
  45. };
  46.  
  47. o = IteratorReverseArray.prototype;
  48.  
  49. o.first = function(){
  50.     this.actIdx = this.obj.length-1;
  51. }
  52.  
  53. o.next = function(){
  54.     --this.actIdx;
  55. }
  56.  
  57. o.isDone = function(){
  58.     return this.actIdx < 0;
  59. }
  60.  
  61. o.hasNext = function(){
  62.     return this.actIdx >= 0;
  63. }
  64.  
  65. o.current = function(){
  66.     if(this.isDone()){
  67.         trace("Iterator out of Bounds: " + this.actIdx + ":" + this.obj.length);   
  68.     }
  69.     return this.obj[this.actIdx];
  70. }
  71.  
  72. //---------------------------------------------------------
  73. //Die Klasse Array bekommt ihre "createIterator"-Methoden zugewiesen
  74. Array.prototype.createIterator = function(){
  75.       return new IteratorArray(this);
  76. }
  77.  
  78. Array.prototype.createIteratorReverse = function(){
  79.       return new IteratorReverseArray(this);
  80. }
  81. //Das braucht ja keiner zu wissen :)
  82. ASSetPropFlags(Array.prototype, null, 1);
  83.  
  84.  
  85.  
  86.  
  87. //---------------------------------------------------------
  88. //---------------------------------------------------------
  89. // Ein Beispiel für normale Arrays:
  90.  
  91. a = [1,2,3,4,5];
  92. trace("----");
  93. it = a.createIterator();
  94. for(it.first(); it.hasNext(); it.next()){
  95.     trace(it.current());
  96. }
  97. trace("----");
  98. it = a.createIteratorReverse();
  99. for(it.first(); it.hasNext(); it.next()){
  100.     trace(it.current());
  101. }
  102. trace("----");

Der Vorteil ist, dass man alle Schleifen dieser Art auf die
gleiche Weise programmieren kann und sich keine Sorgen
darüber machen muss, dass man die Grenzen der Liste
überschreitet. Dafür sorgt ja jetzt der Iterator.

Nur für Arrays alleine bringt das auch noch nicht so viel,
aber wenn man sich jetzt vorstellt, dass eine verlinkte
Liste oder ein Baum oder eine Liste, die nur jedes
zweite ihrer Elemente liefert, auf die gleiche Weise
durchlaufen werden kann, weil sie schliesslich ihren
Iterator selbst zur Verfügung stellen, dann geht einem
plötzlich ein Licht auf.

Es kostet natürlich etwas Performance, also in hochoptimierten
inneren Schleifen ist das vielleicht nicht so angesagt. Aber
oft genug kommt es ja nicht aufs letzte Byte an und optimieren
soll man schliesslich erst zum Schluss.

mfg r.
bokel ist offline   Mit Zitat antworten
Alt 07-04-2003, 19:15   #2 (permalink)
querdenker
 
Benutzerbild von kelor
 
Registriert seit: Jun 2001
Ort: formel1-stadt hockenheim
Beiträge: 4.731
Thumbs up

gefällt mir außerordentlich gut, ralf...

gleich mal testen...*g*

greetz

kelor
kelor ist offline   Mit Zitat antworten
Alt 07-04-2003, 19:33   #3 (permalink)
[Matthias K.] - Moderator
 
Benutzerbild von Madokan
 
Registriert seit: Jun 2001
Ort: Berlin/Germany - and the hole World !
Beiträge: 9.971
ralf auch wenn es performance frist - ist es eine schöne Umsetzung und ich bin sicher die Jungs und Mädels nehmen es dankbar an.

Ich bin sicher der Flash Player wird in zukünftigen version mehr und mehr OOP Kompatibel, ich denk da an C++ u. Java Klassen strukturen, private u. public, etc. mein wunschzettel ist gross - eine Flamme die in mir wohl auch nicht so schnell erlicht!

Wir sollten jedoch froh um jede Erweiterung sein - die fehlerfrei funtzt. War das jetzt eine Anspielung...*hust*

Liebe Grüsse
Matze
Madokan ist offline   Mit Zitat antworten
Alt 07-04-2003, 21:05   #4 (permalink)
hOk
Neuer User
 
Benutzerbild von hOk
 
Registriert seit: Jun 2001
Ort: berlin
Beiträge: 829
Hi,
ich würde den Iterator noch um zwei Methoden
erweitern:
ActionScript:
  1. o.getNextItem = function () {
  2.     var r = this.obj[++this.actIdx];
  3.     if (r == undefined) this.actIdx = 0;
  4.     return r;
  5. }
  6.  
  7. o.getPreviewItem = function () {
  8.     var r = this.obj[--this.actIdx];
  9.     if (r == undefined) this.actIdx = 0; // <-- should maybe this.obj.length - 1 ?
  10.     return r;
  11. }
...dann kann man mit folgender while
Schleife arbeiten:
ActionScript:
  1. var e;
  2. while (e = it.getNextItem()) {
  3.     // do something with e
  4. }
...so kann man sich dann die Reverse-Variante
sparen. Fragwürdig finde ich noch die Reaktion
bei Überschreiten der Grenze, was denkt ihr,
sollte man in beiden Fällen den Pointer auf null
zurücksetzen?

nette Grüße, Holger
__________________
gobogo

Geändert von hOk (07-04-2003 um 21:15 Uhr)
hOk ist offline   Mit Zitat antworten
Alt 07-04-2003, 21:22   #5 (permalink)
helpQLODhelp
 
Benutzerbild von bokel
 
Registriert seit: Feb 2002
Ort: Köln
Beiträge: 8.505
Ja,
das ist möglich.
Aber was passiert, wenn deine Liste
Stellen enthält, die undefined sind ?

Und das mit dem Rückwärtsdurchlaufen ist auch ein
Beispiel dafür, dass das Durchlaufen selbst genau
gleich aussieht und nur durch den Iterator bestimmt
wird.

Das ist ja das eigentlich Ziel der ganzen Anstrengung.
Sozusagen Iterieren ohne Rücksicht auf Verluste.

Genaugenommen ist das zweite Beispiel falsch,
ich ändere das mal. (nee, doch nicht ) Es kann ja
durchaus sein, dass man auch mal rückwärts
iterieren will.
Man könnte sich aber auch eine Klasse vorstellen,
die vom Array abstammt und deren normaler Iterator
eben der Rückwärtsiterator ist. Dann würde man es
von aussen gar nicht mitkriegen, dass es ein Rückwärts-
iterator ist.

mfg r.
bokel ist offline   Mit Zitat antworten
Alt 07-04-2003, 23:48   #6 (permalink)
hOk
Neuer User
 
Benutzerbild von hOk
 
Registriert seit: Jun 2001
Ort: berlin
Beiträge: 829
Zitat:
Geschrieben von bokel
Ja,
das ist möglich.
Aber was passiert, wenn deine Liste
Stellen enthält, die undefined sind ?
Huch, stimmt hast natürlich recht, bokel,
das wäre dann nicht so schön...;-)

grüße, Holger
__________________
gobogo
hOk ist offline   Mit Zitat antworten
Alt 08-04-2003, 09:48   #7 (permalink)
Bugfixer
 
Registriert seit: Nov 2001
Ort: #
Beiträge: 572
lol

Zitat:
Sozusagen Iterieren ohne Rücksicht auf Verluste.
Schaut aber gut aus, Auf den ersten blick ein bischen "high-tech" aber doch recht brauchbar. Ich glaube aber das ich mir sowas gar nicht mehr angewöhnen kann. Wenn mal was richtig komplexes kommt kann ich das ja vielleicht brauchen
secp ist offline   Mit Zitat antworten
Alt 08-04-2003, 19:17   #8 (permalink)
rOb
Alter User
 
Registriert seit: Jun 2001
Ort: Bodensee-Metropole
Beiträge: 1.144
flash goes java!





*froi*
rOb ist offline   Mit Zitat antworten
Alt 13-01-2005, 09:43   #9 (permalink)
Flasher
 
Benutzerbild von achimbode
 
Registriert seit: Sep 2004
Ort: Berlin F-Hain/P-Berg
Beiträge: 43
warum hat das Interface keine current()-Methode?

warum hat das Iterator-Interface eigentlich keine current()-Methode?
hasNext() und next() sind ja schön und gut - aber wenn ich das aktuelle Element nicht abfragen kann, brauche ich die auch nicht.

Gibt es vielleicht ein View-Interface, das current() enthält und das ich zusätzlich implementieren kann, um sicher zu stellen, dass ich eine current()-Methode - oder einige von den anderen Iterator-Methoden von oben - bekomme?
achimbode ist offline   Mit Zitat antworten
Alt 13-01-2005, 12:09   #10 (permalink)
helpQLODhelp
 
Benutzerbild von bokel
 
Registriert seit: Feb 2002
Ort: Köln
Beiträge: 8.505
Interfaces sollen immer möglichst klein sein, und für einen Iterator reichen next und hasNext eigentlich.

ActionScript:
  1. //Ausgabe A,B,C,...,Z
  2. var it:Iterator = new ABCIterator("A", "Z");
  3. while( it.hasNext()){
  4.        trace(it.next());
  5. }

next übernimmt dabei eine Doppelfunktion, es liefert das aktuelle Element und stellt den internen Zeiger eins vor.

mfg. r
bokel ist offline   Mit Zitat antworten
Alt 13-01-2005, 16:09   #11 (permalink)
Flasher
 
Benutzerbild von achimbode
 
Registriert seit: Sep 2004
Ort: Berlin F-Hain/P-Berg
Beiträge: 43
hi bokel,

das dachte ich auch immer, aber Macromedia verwendet das anders:

Zitat:
DataSet.next()

...

Rückgaben
Keine.
achimbode ist offline   Mit Zitat antworten
Alt 13-01-2005, 17:26   #12 (permalink)
helpQLODhelp
 
Benutzerbild von bokel
 
Registriert seit: Feb 2002
Ort: Köln
Beiträge: 8.505
Huh,
und wie kommen die dann an die Werte?
Achso, das ist kein richtiger Iterator, sondern was eingebautes, oder?
mfg r.
bokel ist offline   Mit Zitat antworten
Alt 13-01-2005, 17:57   #13 (permalink)
Flasher
 
Benutzerbild von achimbode
 
Registriert seit: Sep 2004
Ort: Berlin F-Hain/P-Berg
Beiträge: 43
du hattest recht: mx.utils.Iterator.next gibt was zurück...

oh, tschuldigung.
habe gerade festgestellt, dass es in der Definition von mx.utils.Iterator so drinsteht, wie du es beschrieben hast...

besten dank!
achimbode ist offline   Mit Zitat antworten
Alt 02-03-2005, 10:48   #14 (permalink)
Flasher
 
Benutzerbild von achimbode
 
Registriert seit: Sep 2004
Ort: Berlin F-Hain/P-Berg
Beiträge: 43
xml-Iterator

Hi Folks,

vielleicht braucht jemand einen Iterator für XML.
Da ich hier schon soviele gute Sachen gefunden habe, hier meine Version.
Bin natürlich für Verbesserungsvorschläge immer offen...

PHP-Code:
import de.achimbo.xml.iterators.*;

class 
de.achimbo.xml.iterators.DeepIterator implements mx.utils.Iterator{
    
    private var 
structure:XMLNode;    // XML-Struktur, die übergeben wurde
    
private var curnode:XMLNode;    // die Node selbst oder das jeweils aktuelle Child (-> getChild())
    
private var iterator:DeepIterator null// iterator des aktuellen Child
    
private var internDepth:Number;        // Tiefe in der XML-Struktur (0 = dem ersten Konstruktor übergebenes Level)
    
private var selfdone:Boolean false// ist die Node selbst schon zurückgegeben worden (wenn ja, Children zurückgeben!)
    
    
private static var selfNext:Number 0;        // Konstanten für die
    
private static var iteratorNext:Number 1;    // Ansage der "Strategie"
    
private static var childNext:Number 2;    // von hasNext() an next()
    
    
function DeepIterator(structure:XMLNodedepth:Number) {
        if(
structure == null || structure == undefined) throw new de.achimbo.error.AboError(("Parameter structure = " structure), this"Constructor");
        if(
depth == null || depth == undefined) {
            
this.internDepth 0;
        } else {
            
this.internDepth depth;
        }
        
this.structure structure;
        
this.curnode structure;
    }
    
    public function 
next():Object {
        var 
tmp getNext();
        return 
tmp;
    }
    
    public function 
hasNext():Boolean {
        return (
findNext(false)!= null);
    }
    
    private function 
getNext():XMLNode {
        switch(
findNext()){
            case 
0// die (Haupt-)Node wurde noch nicht bearbeitet
                     // die (Haupt-)Node auf bearbeitet setzen
                
selfdone true;
                
// HauptNode zurückgeben
                
return structure;
            case 
1// der Iterator der aktuellen Node (bzw. *dessen* Iterator) hat noch mehr Nodes
                // nächste Iterator-Node zurückgeben
                
return XMLNode(iterator.next());
            case 
2// ein Iterator existiert entweder nicht 
                // oder der Iterator der aktuellen Node hat keine weiteren Nodes,
                // aber es existieren (weitere) Children der Structure-Node
                // nächste ChildNode zur aktuellen machen, ...
                
curnode getChild();
                
// ... von dieser einen Iterator erstellen
                
iterator = new DeepIterator(curnodedepth+1);
                
// wenn dieser Iterator weitere Nodes hat...
                
if(iterator.hasNext()) {
                    
// ... die nächste ( = erste) Node von diesem Iterator ( = die ChildNode selbst) zurückgeben
                    
return XMLNode(iterator.next());
                } else {
                    
// sonst: weiter.
                    
return getNext();
                }
            default: 
// ein Iterator existiert nicht und eine weitere ChildNode auch nicht mehr
                
return null;
        }
    }

    private function 
findNext():Number {
        
// wenn die Haupt-(Structure-)Node noch nicht zurückgegeben ...
        
if(!selfdone) {
            
//Haupt-(Structure-)Node zurückgeben
            
return DeepIterator.selfNext;
        } 
// sonst:
        // wenn ein bestehender Iterator weitere Nodes hat ...
        
if(iterator.hasNext()) { // wenn kein Iterator besteht, ist iterator.hasNext()=undefined -> false
            // ... mit Nodes von bestehendem Iterator fortfahren
            
return DeepIterator.iteratorNext;
        } else { 
// sonst:
            // hat der bestehende Iterator KEINE weitere Nodes:
            
delete iterator// Iterator löschen (Speicher freigeben)...     
            //(wenn kein Iterator vorhanden, wird eben undefined gelöscht...)
            
iterator null// ... und auf Null setzen 
        
}
        
// die Haupt-(Structure-)Node ist bearbeitet und es besteht kein Iterator:
        // wenn weiteres Child vorhanden ...
        
if(getChild() != null) {
            
// ... mit nächstem Child weitermachen
            
return DeepIterator.childNext;
        }
        return 
null;
    }
    
    private function 
getChild():XMLNode {
        
// wenn oberste Node keine Children hat, NULL zurück (-> hasNext = false)
        
if(!structure.hasChildNodes()) return null;
        if(
curnode === structure) {
            return 
curnode.firstChild;
        }
        return 
curnode.nextSibling// nextSibling gibt NULL zurück, falls kein weiterer Sibling existiert
    
}

//////////////////// DEBUG-Area (kann weggelassen werden) ///////////////////////
    
    
public function get depth():Number {
        
/* DEBUG + toString() only ........................ */
        
if(iterator != null) return iterator.depth;
        return 
internDepth;
    }
    
    private function 
traceNode(node:XMLNode):String {
        
/* DEBUG + toString() only ........................ */
        
return "<" node.nodeName ">" node.nodeValue "</" node.nodeName ">"
    }
    
    public function 
toString():String {
        var 
einzug:String "";
        for(var 
i=0i<depthi++) {
            
einzug += "   ";
        }
        return 
einzug "DeepIterator" traceNode(structure);
    }

achimbode ist offline   Mit Zitat antworten
Antwort

Lesezeichen

Themen-Optionen
Ansicht

Forumregeln
Es ist Ihnen nicht erlaubt, neue Themen zu verfassen.
Es ist Ihnen nicht erlaubt, auf Beiträge zu antworten.
Es ist Ihnen nicht erlaubt, Anhänge hochzuladen.
Es ist Ihnen nicht erlaubt, Ihre Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks sind an
Pingbacks sind an
Refbacks sind an



Alle Zeitangaben in WEZ +1. Es ist jetzt 15:39 Uhr.

Domains, Webhosting & Vserver von Host Europe
Unterstützt das Flashforum!
Adobe User Group


Copyright ©1999 – 2012 Marc Thiele