Iterator Pattern

The Iterator Pattern provides a way to sequentially access the elements of an aggregate object without exposing the object's internal implementation. This allows for accessing the internal data of the collection transparently from external code. The Iterator Pattern belongs to the behavioral design pattern.

Description

The Iterator Pattern is designed for collection objects, which are likely to involve operations such as adding and deleting elements, as well as supporting the traversal of collection elements. At this point, we can place the traversal operation in the collection object, but in doing so, the collection object takes on too much responsibility. One of the principles of object-oriented design is the Single Responsibility Principle, so we should try to separate these responsibilities and use different classes to take on different responsibilities. The Iterator Pattern uses the iterator class to take on the responsibility of traversing the collection.

Advantages

  • Support traversing a collection object in different ways, and can simplify the aggregate class.
  • Multiple traversals can be performed on the same aggregate.
  • In the Iterator Pattern, adding new aggregate classes and iterator classes is very convenient and does not require modifying the original code.
  • The Iterator Pattern allows accessing the content of an aggregate object without exposing its internal representation, that is, abstract iteration.
  • The Iterator Pattern provides a unified interface for traversing different collection structures, thus supporting the same algorithm to operate on different collection structures.

Disadvantages

  • The Iterator Pattern separates the responsibilities of storing and traversing data, requiring the corresponding increase in the number of iterator classes when adding new aggregate classes, which increases the complexity of the system to some extent.
  • Modifying the structure of the collection while iterating with the iterator may lead to exceptions, and it is not possible to change the number of elements in the collection while iterating.

Applicable Scenarios

  • Access the content of an aggregate object without exposing its internal representation.
  • Need to provide multiple traversal methods for aggregate objects.
  • Provide a unified interface for traversing different aggregate structures.

Implementation

// Radio Station Example

class RadioStation {
    constructor(frequency) {
        this.frequency = frequency;
    }
    
    getFrequency() {
        return this.frequency;
    }
}

class StationList {
    constructor(){
        this.index = -1;
        this.stations = [];
    }

    get(i){
        return this.stations[this.index];
    }

    hasNext(){
        let index = this.index + 1;
        return this.stations[index] !== void 0;
    }

    next(){
        return this.stations[++this.index];
    }

    addStation(station) {
        this.stations.push(station);
    }
    
    removeStation(toRemove) {
        const toRemoveFrequency = toRemove.getFrequency();
        this.stations = this.stations.filter(station => station.getFrequency() !== toRemoveFrequency);
    }
}

(function(){
    const stationList = new StationList();
    stationList.addStation(new RadioStation(89));
    stationList.addStation(new RadioStation(101));
    stationList.addStation(new RadioStation(102));
    stationList.addStation(new RadioStation(103.2));
    stationList.stations.forEach(station => console.log(station.getFrequency())); // 89 101 102 103.2
    stationList.removeStation(new RadioStation(89));
    while(stationList.hasNext()) console.log(stationList.next().getFrequency()); // 101 102 103.2
})();

Everyday Question

https://github.com/WindrunnerMax/EveryDay

Reference

https://www.cnblogs.com/xuwendong/p/9898030.html https://www.runoob.com/design-pattern/iterator-pattern.html https://github.com/sohamkamani/javascript-design-patterns-for-humans#-iterator