Design pattern - example of iterator pattern in Java

Scenes

In order to develop a sales management system, when analyzing and designing the system, it is found that it is often necessary to traverse the product data and customer data in the system,

In order to reuse these traversal codes, developers designed an abstract data collection class AbstractObjectList, and the class that will store data such as commodities and customers

Subclasses ProductList and CustomerList as subclasses of the AbstractObjectList class are used to store product data and customer data respectively.

In software development, we often need to use aggregate objects to store a series of data. Aggregation objects have two responsibilities: one is to store data;

The second is to traverse the data. From the perspective of dependency, the former is the basic responsibility of aggregate objects; while the latter is both changeable and separable.

Therefore, the behavior of traversing data can be separated from the aggregation object and encapsulated in an object called an "iterator".

The iterator provides the behavior of traversing the data inside the aggregated object, which simplifies the design of the aggregated object and better meets the requirements of the "Single Responsibility Principle".

iterator pattern

Iterator Pattern:

Provides a method to access the aggregate object without exposing the object's internal representation, its alias for the cursor (Cursor).

The iterator pattern is an object behavioral pattern

Iterator pattern structure diagram

The following roles are included in the iterator pattern structure diagram:

Iterator (abstract iterator):

It defines an interface for accessing and traversing elements, declares methods for traversing data elements,

For example:

The first() method for getting the first element, the next() method for accessing the next element, the hasNext() method for judging whether there is another element,

The currentItem() method used to obtain the current element, etc., will be implemented in the specific iterator.

ConcreteIterator (concrete iterator):

It implements the abstract iterator interface, completes the traversal of the aggregate object, and records the current position in the aggregate object through the cursor in the specific iterator.

When implemented, the cursor is usually a non-negative integer representing the position.

Aggregate (abstract aggregation class):

It is used to store and manage element objects, declare a createIterator() method to create an iterator object, and act as an abstract iterator factory.

ConcreteAggregate (concrete aggregation class):

It implements the createIterator() method declared in the abstract aggregate class, which returns a ConcreteIterator instance corresponding to the concrete aggregate class.

Note:

Blog:
Domineering Rogue Temperament_C#, Architecture Road, SpringBoot-CSDN Blog

accomplish

1. Create a new abstract aggregation class

import java.util.ArrayList;
import java.util.List;

//在本例中,为了详细说明自定义迭代器的实现过程,没有使用JDK中内置的迭代器,事实上,JDK内置迭代器已经实现了对一个List对象的正向遍历
//抽象聚合类
abstract class AbstractObjectList {
    protected List<Object> objects = new ArrayList<>();

    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;
    }

    //声明创建迭代器对象的抽象工厂方法
    public abstract AbstractIterator createIterator();
}

2. Create a new abstract iterator

//抽象迭代器
interface AbstractIterator {
    //移至下一个元素
    public void next();
    //判断是否为最后一个元素
    public boolean isLast();
    //移至上一个元素
    public void previous();
    //判断是否为第一个元素
    public boolean isFirst();
    //获取下一个元素
    public Object getNextItem();
    //获取上一个元素
    public Object getPreviousItem();
}

3. Create a new specific aggregation class: commodity data class

import java.util.List;

//商品数据类:具体聚合类
public class ProductList extends AbstractObjectList{

    public ProductList(List objects) {
        super(objects);
    }

    //实现创建迭代器对象的具体工厂方法
    public AbstractIterator createIterator() {
        return new ProductIterator(this);
    }
}

4. Create a specific iterator: product iterator

import java.util.List;

//商品迭代器:具体迭代器
public class ProductIterator implements AbstractIterator{
    private ProductList productList;
    private List products;
    private int cursor1; //定义一个游标,用于记录正向遍历的位置
    private int cursor2; //定义一个游标,用于记录逆向遍历的位置

    public ProductIterator(ProductList list){
        this.productList = list;
        this.products = list.getObjects();//获取集合对象
        cursor1 = 0;//设置正向遍历游标的初始值
        cursor2 = products.size() -1 ; //设置逆向遍历游标的初始值
    }

    public void next() {
        if(cursor1<products.size()){
            cursor1++;
        }
    }


    public boolean isLast() {
        return (cursor1 == products.size());
    }


    public void previous() {
        if(cursor2>-1){
            cursor2--;
        }
    }


    public boolean isFirst() {
        return (cursor2 == -1);
    }


    public Object getNextItem() {
        return products.get(cursor1);
    }


    public Object getPreviousItem() {
        return products.get(cursor2);
    }
}

5. Client call

import java.util.ArrayList;
import java.util.List;

public class Client {
    public static void main(String[] args) {
        List products = new ArrayList();
        products.add("商品1");
        products.add("商品2");
        products.add("商品3");
        products.add("商品4");

        AbstractObjectList list;
        AbstractIterator iterator;

        list = new ProductList(products);//创建聚合对象
        iterator = list.createIterator();//创建迭代器对象

        System.out.println("正向遍历");
        while (!iterator.isLast()){
            System.out.println(iterator.getNextItem()+",");
            iterator.next();
        }
        System.out.println("逆向遍历");
        while (!iterator.isFirst()){
            System.out.println(iterator.getPreviousItem()+",");
            iterator.previous();
        }
    }
}

6. Summary

The iterator pattern is a very frequently used design pattern. By introducing an iterator, the data traversal function can be separated from the aggregation object.

Aggregation objects are only responsible for storing data, while traversing data is done by iterators. Since the class libraries of many programming languages ​​have implemented the iterator pattern,

Therefore, in actual development, we only need to directly use the iterators defined in Java, C# and other languages. The iterators have become our operation

One of the basic tools for aggregating objects.

The main advantages of the iterator pattern are as follows:

(1) It supports traversing an aggregate object in different ways, and multiple traversal methods can be defined on the same aggregate object. in iterator mode

We only need to replace the original iterator with a different iterator to change the traversal algorithm, and we can also define the subclass of the iterator ourselves

To support new traversal methods.

(2) Iterators simplify aggregation classes. Due to the introduction of iterators, there is no need to provide methods such as data traversal in the original aggregation object.

This simplifies the design of aggregate classes.

(3) In the iterator mode, due to the introduction of the abstraction layer, it is very convenient to add new aggregation classes and iterator classes without modifying the original code.

Meet the "open-closed principle" requirements.

The main disadvantages of the iterator pattern are as follows:

(1) Since the iterator mode separates the responsibilities of storing data and traversing data, adding a new aggregation class requires correspondingly adding a new iterator class,

The number of classes increases in pairs, which increases the complexity of the system to a certain extent.

(2) The design of the abstract iterator is difficult, and the future expansion of the system needs to be fully considered. For example, the JDK built-in iterator Iterator cannot realize reverse traversal.

If you need to implement reverse traversal, you can only implement it through its subclass ListIterator, etc., and the ListIterator iterator cannot be used to operate the aggregation object of Set type.

When customizing iterators, it is not easy to create a comprehensive abstract iterator.

Consider using the iterator pattern when:

(1) Access the contents of an aggregate object without exposing its internal representation. Separating access to aggregated objects from storage of internal data makes accessing aggregated objects

No knowledge of its internal implementation details is required.

(2) It is necessary to provide multiple traversal methods for an aggregated object.

(3) Provide a unified interface for traversing different aggregation structures, and provide different traversal methods for different aggregation structures in the implementation class of the interface,

The client can operate the interface consistently.

Guess you like

Origin blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/132004772