17. Iterator

Iterator Pattern: Provides a way to access an aggregated object without exposing its internal representation, nicknamed Cursor. Iterator pattern is an object behavior pattern.

The iterator pattern consists of the following roles:

Iterator (abstract iterator): It defines interfaces for accessing and traversing elements and declares methods for traversing data elements, such as the first() method for obtaining the first element, the next() method for accessing the next element, the hasNext() method for judging whether there is another element, the current Item () method for obtaining the current element, and so on. These methods will be implemented in the iterator.
ConcreteIterator (concrete iterator): It implements the abstract iterator interface, completes the traversal of aggregated objects, and records the current position of aggregated objects through cursors in concrete iterators. In concrete implementation, the cursor is usually a non-negative integer representing the position.
Aggregate: It stores and manages element objects, declares a createIterator() method for creating an iterator object and acts as an abstract iterator factory.
ConcreteAggregate: It implements the createIterator() method declared in the abstract aggregate class, which returns a concrete iterator instance corresponding to the concrete aggregate class.

1. Main Advantages

(1) It supports traversing an aggregated object in different ways, and can define multiple traversing modes on the same aggregated object. In the iterator pattern, the traversal algorithm can be changed by replacing the original iterator with a different iterator. We can also define the subclasses of iterators to support the new traversal method.
(2) Iterators simplify aggregation classes. Because of the introduction of iterator, there is no need to provide data traversal methods in the original aggregation objects, which can simplify the design of aggregation classes.
(3) In the iterator model, because of the introduction of abstraction layer, it is convenient to add new aggregation classes and iterator classes without modifying the original code to meet the requirements of the "Open-Close Principle".

2. Main shortcomings

(1) Because the iterator pattern separates the responsibility of storing and traversing data, adding new aggregated classes requires adding new iterator classes corresponding to increasing the number of classes in pairs, which increases the complexity of the system to a certain extent.
(2) The design of abstract iterator is very difficult, and we need to take full account of the future expansion of the system. For example, the JDK built-in iterator Iterator can not achieve reverse traversal. If we need to achieve reverse traversal, we can only implement it through its subclass ListIterator and so on, while ListIterator iterator can not be used to manipulate aggregated objects of Set type. When creating a custom iterator, it is not easy to create a comprehensive Abstract iterator.

3. Applicable Scenario

(1) Accessing the content of an aggregated object without exposing its internal representation. The access of aggregated objects is separated from the storage of internal data, so that the internal implementation details of aggregated objects need not be understood when accessing them.
(2) It is necessary to provide a variety of traversal methods for an aggregated object.
(3) Provide a unified interface for traversing different aggregation structures, and provide different traversing methods for different aggregation structures in the implementation class of the interface, while the client can operate the interface consistently.

Iterator mode in King Glory (Hero Browse):

/**
 * 2018/12/6
 * Abstract aggregation class
 *
 * @author machuanpeng
 */
public abstract class AbstractObjectList {
    
	protected List<Object> objects = new ArrayList<Object>();
 
	public AbstractObjectList(List objects) {
		this.objects = objects;
	}
	
	public void addObject(Object obj) {
		this.objects.add(obj);
	}
	
	public void removeObject(Object obj) {
		this.objects.remove(obj);
	}
	
	public List getObjects() {
		return this.objects;
	}
	
    //Declare an abstract factory method for creating iterator objects
	public abstract AbstractIterator createIterator();
}
/**
 * 2018/12/6
 * Heroes List Aggregation Class
 *
 * @author machuanpeng
 */
public class HeroList extends AbstractObjectList {
	public HeroList(List products) {
		super(products);
	}
	
    /**A concrete factory method for creating iterator objects*/
	public AbstractIterator createIterator() {
		return new HeroIterator(this);
	}
}
/**
 * 2018/12/6
 * Abstract iterator
 *
 * @author machuanpeng
 */
interface AbstractIterator {
	public void next(); //Move to the next element
	public boolean isLast(); //Determine whether it is the last element
	public void previous(); //Move to the previous element
	public boolean isFirst(); //Determine whether it is the first element
	public Object getNextItem(); //Get the next element
	public Object getPreviousItem(); //Get the previous element
}
public class HeroIterator implements AbstractIterator {
	private HeroList heroList;
	private List heros;
	private int cursor1; //Define a cursor to record the position of forward traversal
	private int cursor2; //Define a cursor to record the location of the reverse traversal
	
	public HeroIterator(HeroList list) {
		this.heroList = list;
		this.heros = list.getObjects(); //Getting Collection Objects
		cursor1 = 0; //Set the initial value of the forward traversal cursor
		cursor2 = heros.size() -1; //Setting the initial value of the reverse traversal cursor
	}
	
	public void next() {
		if(cursor1 < heros.size()) {
			cursor1++;
		}
	}
	
	public boolean isLast() {
		return (cursor1 == heros.size());
	}
	
	public void previous() {
		if (cursor2 > -1) {
			cursor2--;
		}
	}
	
	public boolean isFirst() {
		return (cursor2 == -1);
	}
	
	public Object getNextItem() {
		return heros.get(cursor1);
	} 
		
	public Object getPreviousItem() {
		return heros.get(cursor2);
	} 	
}

Test:

public class Client {
	public static void main(String args[]) {
		List heros = new ArrayList();
		heros.add("A hundred miles to keep the promise");
		heros.add("Cattle Devil");
		heros.add("Dianwei");
		heros.add("Zhen Ji");
		heros.add("Damo");
			
		AbstractObjectList list;
		AbstractIterator iterator;
		
		list = new HeroList(heros); //Create aggregate objects
		iterator = list.createIterator();	//Create iterator objects
		
		System.out.println("Forward traversal:");	
		while(!iterator.isLast()) {
			System.out.print(iterator.getNextItem() + ",");
			iterator.next();
		}
		System.out.println("-----------------------------");
		System.out.println("Reverse traversal:");
		while(!iterator.isFirst()) {
			System.out.print(iterator.getPreviousItem() + ",");
			iterator.previous();
		}
	}
}

Tags: Programming JDK

Posted on Thu, 10 Oct 2019 04:52:28 -0700 by intermediate