typescript: Iterator Pattern

发布时间 2023-10-11 18:10:11作者: ®Geovin Du Dream Park™

 

/**
 * Iterator Pattern 迭代器是一种行为设计模式, 让你能在不暴露复杂数据结构内部细节的情况下遍历其中所有的元素
 * file: Iteratorts.ts   npm install -g babel-cli
 * Intent: Lets you traverse elements of a collection without exposing its
 * underlying representation (list, stack, tree, etc.).
 */

interface Iterator<T> { //,any,undefined
    /**
     * Return the current element.
     */
    current(): T;//string; //

    /**
     * Return the current element and move forward to next element.
     */
    next(): T;//string; //T

    /**
     * Return the key of the current element.
     */
    key(): number;

    /**
     * Checks if current position is valid.
     */
    valid(): boolean;

    /**
     * Rewind the Iterator to the first element.
     */
    rewind(): void;
}

/**
 * 
 */
interface Aggregator {
    /**
     * Retrieve an external iterator.
     */
    getIterator(): Iterator<string>; // ,any,undefined
}

/**
 * Concrete Iterators implement various traversal algorithms. These classes
 * store the current traversal position at all times. ,any,undefined
 */

 class AlphabeticalOrderIterator implements Iterator<string> {  //new AlphabeticalOrderIterator(this, true)  Iterator<string, any, undefined>

    private collection: WordsCollection;

    //aggregates: Aggregator[]



    /**
     * Stores the current traversal position. An iterator may have a lot of
     * other fields for storing iteration state, especially when it is supposed
     * to work with a particular kind of collection.
     */
    private position: number = 0;

    /**
     * This variable indicates the traversal direction.
     */
    private reverse: boolean = false;
    /**
     * 
     * @param collection 
     * @param reverse 
     */
    constructor(collection: WordsCollection, reverse: boolean = false) {

        this.collection = collection;
        this.reverse = reverse;
     

        if (reverse) {
            this.position = collection.getCount() - 1;
        }
    }

    /**
     * 
     */
    public rewind() {
        this.position = this.reverse ?
            this.collection.getCount() - 1 :
            0;
    }

    /**
     * 
     * @returns 
     */
    public current(): string {
        return this.collection.getItems()[this.position];
    }

    /**
     * 
     * @returns 
     */
    public key(): number {
        return this.position;
    }

    /**
     * 
     * @returns 
     */
    public next() {

        let item="";
        //item = this.collection.getItems()[this.position];
        //this.position += this.reverse ? -1 : 1;
        //return item;

       /* item = this.collection.getItems()[this.position].toString();
        this.position += this.reverse ? -1 : 1;
       */
       if (this.position < this.collection.getCount.length) {
            const aggregate = this.collection[this.position]
            this.position += 1
            
            return aggregate
        }  
        item = this.collection.getItems()[this.position];
        this.position += this.reverse ? -1 : 1;
        return item; 
       // throw new Error('At End of Iterator'); 
    }
    /**
     * 
     * @returns 
     * 
     */
    public valid(): boolean {
        if (this.reverse) {
            return this.position >= 0;
        }

        return this.position < this.collection.getCount();
    }
}

/**
 * Concrete Collections provide one or several methods for retrieving fresh
 * iterator instances, compatible with the collection class.
 */
class WordsCollection implements Aggregator {

    /**
     * 
     */
    private items: string[] = [];

    /**
     * 
     * @returns 
     */
    public getItems(): string[] {
        return this.items;
    }

    /**
     * 
     * @returns 
     */
    public getCount(): number {
        return this.items.length;
    }
    /**
     * 
     * @param item 
     */
    public addItem(item: string): void {
        this.items.push(item);
    }
    /**
     * 
     * @returns 
     */
    public getIterator(): Iterator<string> {
        let str="";
        //str=new AlphabeticalOrderIterator(this).next().getIterator();
       let d= new AlphabeticalOrderIterator(this).next();
        //return;
        return new AlphabeticalOrderIterator(this);
    }
    /**
     * 
     * @returns 
     */
    public getReverseIterator(): Iterator<string> {
        let str="";
        //new AlphabeticalOrderIterator(this, true).next();
        //return ;
        return new AlphabeticalOrderIterator(this, true);
    }
}




/**
 * 2. 
 */
interface IIterator {
    next(): IAggregate
    // Return the object in collection

    hasNext(): boolean
    // Returns Boolean whether at end of collection or not
}

class IteratorConcept implements IIterator {
    // The concrete iterator (iterable)
    index: number
    aggregates: IAggregate[]

    constructor(aggregates: IAggregate[]) {
        this.index = 0
        this.aggregates = aggregates
    }

    next() {
        if (this.index < this.aggregates.length) {
            const aggregate = this.aggregates[this.index]
            this.index += 1
            return aggregate
        }
        throw new Error('At End of Iterator')
    }

    hasNext() {
        return this.index < this.aggregates.length
    }
}

interface IAggregate {
    // An interface that the aggregates should implement
    method(): string  //void
}

class Aggregate implements IAggregate {
    // A concrete object
    method(): string { //void
        let str="";
        console.log('This method has been invoked')
        str="This method has been invoked";
        return str;
    }
}

// The Client
const AGGREGATES = [
    new Aggregate(),
    new Aggregate(),
    new Aggregate(),
    new Aggregate(),
]


let pubIter1="";
let pubIter2="";
let pubIter3="Geovin Du";
let pubIter4="geovindu";

// AGGREGATES is an array that is already iterable by default.
// but we can create own own iterator on top anyway.
const ITERABLE = new IteratorConcept(AGGREGATES)

while (ITERABLE.hasNext()) {
    pubIter1=pubIter1+","+ ITERABLE.next().method()
}

/**
 * 1. The client code may or may not know about the Concrete Iterator or Collection
 * classes, depending on the level of indirection you want to keep in your
 * program.
 */
const collection = new WordsCollection();
collection.addItem('First');
collection.addItem('Second');
collection.addItem('Third');

const iterator = collection.getIterator();
/**/
console.log('Straight traversal:');
let cc=0;
//while (iterator.valid())
//pubIter2=pubIter2+iterator.current();
for(cc=0;cc<collection.getCount();cc++) {
    let getstr=iterator.next();
    console.log(getstr);
    pubIter2=pubIter2+getstr;
}

console.log('');
console.log('Reverse traversal:');
const reverseIterator = collection.getReverseIterator();
//pubIter3=pubIter3+reverseIterator.current();
//while (reverseIterator.valid()) {
    //console.log(reverseIterator.next());
let dui=0;
for(dui=0;dui<collection.getCount();dui++)
{
    let getstr=reverseIterator.next();
    console.log(getstr);
    pubIter3=pubIter3+getstr;
}

//}

let messageIter: string = 'Hello World,This is a typescript!,涂聚文 Geovin Du.Web';
document.body.innerHTML = messageIter+",<br/>one="+pubIter1+",<br/>two="+pubIter2+",<br/>three="+pubIter3+",<br/>four="+pubIter4+",<br/>TypeScript Iterator Design Pattern  迭代器模式";

  

调用:

<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <head><title>TypeScript Hello Iterator Design Pattern 迭代器</title>
      <meta name="Description" content="geovindu,涂聚文,Geovin Du"/>
<meta name="Keywords" content="geovindu,涂聚文,Geovin Du"/>
<meta name="author" content="geovindu,涂聚文,Geovin Du"/> 
    </head>
    <body>

        <script src="dist/Iteratorts.js">
 //
            //type="module"
        </script>

    </body>
</html>

  

 

输出: