banner
jzman

jzman

Coding、思考、自觉。
github

Iterator Design Pattern

PS: Anything beautiful becomes less precious when it becomes commonplace.

The iterator design pattern is a commonly used design pattern that provides a way to sequentially access various elements in an aggregate object without exposing the internal representation of the object. The iterator design pattern belongs to the behavioral design pattern.

  1. Related Concepts
  2. Use Cases
  3. Java Implementation
  4. Dart Implementation
  • Abstract Aggregate Role: Defines methods for adding, deleting, and creating iterators for the aggregate object.
  • Concrete Aggregate Role: Concrete implementation class of the abstract aggregate role.
  • Abstract Iterator Role: Defines iterator-related methods, such as hasNext, first, last, etc.
  • Concrete Iterator Role: Concrete implementation class of the abstract iterator role.

Use Cases#

The use cases of the iterator design pattern are as follows:

  1. Provide a traversal method for a specific data structure.
  2. Use the iterator design pattern to hide the implementation details of the aggregate object.
  3. When there are multiple aggregate objects, using the iterator design pattern can shield the differences caused by different data structures.

Java Implementation#

Implement the iterator design pattern simply. Define the abstract aggregate role as follows:

/**
 * Abstract aggregate role
 * Created by jzman
 * Powered by 2019/12/22.
 */
interface Aggregate {
    Iterator createIterator();
}

Define the abstract iterator role as follows:

/**
 * Abstract iterator role
 * Created by jzman
 * Powered by 2019/12/22.
 */
interface Iterator {
    Object first();
    Object next();
    boolean isDone();
    Object currentItem();
}

Implement the concrete aggregate role and concrete iterator role as follows:

/**
 * Concrete aggregate role
 * Created by jzman
 * Powered by 2019/12/22.
 */
class ConcreteAggregate implements Aggregate {
    private List<Object> mList;
    
    public ConcreteAggregate(List<Object> mList) {
        this.mList = mList;
    }
    
    @Override
    public Iterator createIterator() {
        return new ConcreteIterator();
    }

    /**
     * Concrete iterator role
     */
    private class ConcreteIterator implements Iterator {

        private int mCursor;

        @Override
        public Object first() {
            return mList.get(0);
        }

        @Override
        public Object next() {
            mCursor++;
            if (mCursor < mList.size()) {
                return mList.get(mCursor);
            }
            return null;
        }

        @Override
        public boolean isDone() {
            return mCursor >= mList.size();
        }

        @Override
        public Object currentItem() {
            return mList.get(mCursor);
        }
    }
}

Test the above code:

/**
 * Iterator test
 * Created by jzman
 * Powered by 2019/12/22.
 */
class Client {
    public static void main(String[] args) {
        List<Object> objects = new ArrayList<>();
        objects.add("A");
        objects.add("B");
        objects.add("C");
        ConcreteAggregate aggregate = new ConcreteAggregate(objects);

        // Get the iterator
        Iterator iterator = aggregate.createIterator();
        // Traverse
        while (!iterator.isDone()) {
            Object o = iterator.currentItem();
            System.out.println("data:" + o);
            iterator.next();
        }
    }
}

The test result is as follows:

data:A
data:B
data:C

Dart Implementation#

main(){
  List<Object> mList = ["A","B","C"];
  Aggregate aggregate = new ConcreteAggregate(mList);
  Iterator iterator = aggregate.createIterator();
  while (!iterator.isDone()) {
    Object obj = iterator.currentItem();
    print("data:${obj.toString()}");
    iterator.next();
  }
}

// Abstract iterator role
abstract class Iterator{
  Object first();
  Object next();
  bool isDone();
  Object currentItem();
}

// Concrete iterator role
class ConcreteIterator implements Iterator{
  int mCursor = 0;
  List<Object> mList;

  ConcreteIterator(this.mList);

  @override
  Object first() {
      return mList[0];
  }

  @override
  Object next() {
      mCursor++;
      if (mCursor < mList.length) {
          return mList[mCursor];
      }
      return null;
  }

  @override
  bool isDone() {
      return mCursor >= mList.length;
  }

  @override
  Object currentItem() {
      return mList[mCursor];
  }
}

// Abstract aggregate role
abstract class Aggregate {
  Iterator createIterator();
}

// Concrete aggregate role
class ConcreteAggregate implements Aggregate{
  List<Object> mList;
  ConcreteAggregate(this.mList);
  @override
  Iterator createIterator(){
    return new ConcreteIterator(mList);
  }
}

The test result is as follows:

data:A
data:B
data:C

Although the iterator design pattern is often used when traversing collections, it may not have any concept of design patterns when used, but such concepts will subtly improve one's coding ability.

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.