一.迭代器模式介绍

迭代器模式(Iterator Pattern)又称为游标(Cursor)模式,是行为型设计模式之一。

源于对容器的访问,比如java中的listMap,数组等,我们知道对容器对象的访问必然是多种多样的所以我们把遍历的方法封装在容器中,或者不提供遍历方法

 

1.如果我们将遍历的方法封装到容器中,那么对于容器类来说就承担了过多的功能,容器类不仅要维护自身内部的数据元素而且还要对外提供遍历的接口方法.

2.如果我们不提供遍历方法而让使用者自己去实现,又会让容器的内部袭击暴露无遗

所以迭代器模式应运而生,在客户访问类与容器体之间插入一个第三者(迭代器)

 

二.迭代器模式的定义

提供一种方法顺序访问一个容器对象中的各个元素,而又不需要暴露该对象的内部表示

 

三.迭代器模式的使用场景

遍历一个容器对象时

 

四.个人理解

其实就跟每个人去抓娃娃一样,都能抓到娃娃,但是用爪子的姿势各有不同,所以这里的Iterator就相当于把所有方法都封装起来一样

五.基本实例

//Iterator.java

**
 * Created by Administrator on 2016/5/8 0008.
 * 迭代器接口
 */
public interface Iterator<T> {
    /**
     * 是否还有下一个元素
     * @return  true 表示有,false 表示没有
     * */
    boolean hasNext();

    /**
     * 返回当前位置的元素并将位置移至下一位
     * */
     T next();


}

//ConcreteIterator.java

/**
 * Created by Administrator on 2016/5/8 0008.
 * 具体迭代器
 */
public class ConcreteIterator<T> implements Iterator{
    private List<T> list = new ArrayList<>();
    private int cursor = 0;

    @Override
    public boolean hasNext() {
        return cursor != list.size();
    }

    @Override
    public Object next() {
        T obj = null;
        if(this.hasNext()){
            obj = this.list.get(cursor++);
        }
        return obj;
    }
}

//Aggregate.java

/**
 * Created by Administrator on 2016/5/8 0008.
 * 容器接口
 */
public interface Aggregate<T> {
    /**
     * 添加一个元素
     * @param obj 元素对象
     * */
    void add(T obj);

    /**
     * 移除一个元素
     * @param obj 元素对象
     * */
    void remove(T obj);

    /**
     * 获取容器的迭代器
     * @return 迭代器对象
     * */
    Iterator<T>  iterator();

}


//ConcreteAggregate.java

/**
 * Created by Administrator on 2016/5/8 0008.
 * 具体容器接口
 */
public class ConcreteAggregate<T> implements Aggregate<T>{
    private List<T> list = new ArrayList<>();

    @Override
    public void add(T obj) {
        list.add(obj);
    }

    @Override
    public void remove(T obj) {
        list.remove(obj);
    }

    @Override
    public Iterator<T> iterator() {
        return new ConcreteIterator<>();
    }
}


//Client.java

/**
 * Created by Administrator on 2016/5/8 0008.
 */
public class Client {
    public static void main(String[] args){
        Aggregate<String> a = new ConcreteAggregate<>();
        a.add("Aige");
        a.add("Studio\n");
        a.add("SM");
        a.add("Brother");
        Iterator<String> i = a.iterator();
        while(i.hasNext()){
            System.out.println(i.next());
        }
    }
}

角色介绍

Iterator:迭代器接口

迭代器接口负责定义,访问和遍历元素的接口。

Concrete Iterator:具体迭代器类

具体迭代器类的目的主要是实现迭代器接口,并记录遍历的当前位置。

Aggregate:容器接口

容器接口负责提供创建具体迭代器角色的接口

Concrete Aggregate :具体容器类。

Client:客户类



六.模式的简单实现

老板  需要统计各个部门的人数,但是每个部门统计方式不一样,但是老板总不能用不同的方式遍历吧

//Employee.java

**
 * Created by Administrator on 2016/5/8 0008.
 */
public class Employee {
    private String name;
    private int age;
    private String sex;
    private String position;

    public Employee(String name, int age, String sex, String position) {
        this.name = name;
        this.age = age;
        this.sex = sex;
        this.position = position;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", sex='" + sex + '\'' +
                ", position='" + position + '\'' +
                '}';
    }
}

//CompanyMin.java(部门A)

/**
 * Created by Administrator on 2016/5/8 0008.
 */
public class CompanyMin implements Company{
    private List<Employee> list = new ArrayList<>();

    public CompanyMin(){
        list.add(new Employee("小民",96,"男","程序猿"));
        list.add(new Employee("小芸",22,"女","测试"));
        list.add(new Employee("小方",18,"女","测试"));
        list.add(new Employee("可儿",21,"女","设计"));
        list.add(new Employee("朗情",19,"女","设计"));
    }

    public List<Employee> getEmployee(){
        return list;
    }


    /**
     * 新加的
     * */
    @Override
    public Iterattor iterator() {
        return new MinIterator(list);
    }


}


//CompanyHui.java(部分B)

/**
 * Created by Administrator on 2016/5/8 0008.
 */
public class CompanyHui implements Company {
    private Employee[] array = new Employee[3];

    public CompanyHui(){
        array[0] = new Employee("辉哥",108,"男","程序猿");
        array[1] = new Employee("小红",98,"男","测试");
        array[2] = new Employee("小辉",88,"男","测试");
    }

    public Employee[] getEmployee(){
        return array;
    }

    @Override
    public Iterattor iterator() {
        return new HuiIterator(array);
    }
}


//Boss.java

/**
 * Created by Administrator on 2016/5/8 0008.
 */
public class Boss {
    public static void main(String[] args){
        //这是老方法  缺点:查看不同部门的信息,我们都要在Boss类中增加一段遍历逻辑  这时候可以用迭代器实现,将遍历逻辑封装
//        CompanyMin min = new CompanyMin();
//        List minList = min.getEmployee();
//        for(int i=0;i<minList.size();i++){
//            System.out.println(minList.get(i).toString());
//        }
//
//        CompanyHui hui = new CompanyHui();
//        Employee[] huiArray = hui.getEmployee();
//        for(int i = 0;i<huiArray.length;i++){
//            System.out.println(huiArray[i]);
//        }

        //这是新方法
        CompanyMin min = new CompanyMin();
        check(min.iterator());
        CompanyHui hui = new CompanyHui();
        check(hui.iterator());
    }
    private static void check(Iterattor iterator){
        while(iterator.hasNext()){
            System.out.println(iterator.next().toString());
        }
    }
}

上面的代码没问题,老板也能查看到信息,但是其他部门的人员信息也有各自不同的实现,遍历不同容器再Boss类中增加一个端逻辑

所以要用下面的代码(优化过后)


//Iterator.java

/**
 * Created by Administrator on 2016/5/8 0008.
 */
public interface Iterattor<T> {
    /**
     * 是否还有下一个元素
     * @return true 表示有 , false 表示没有
     * */
    boolean hasNext();

    /**
     * 返回当前位置的元素,并将位置移至下一位
     * */
    T next();
}

//MinIterator.java(部门A)

/**
 * Created by Administrator on 2016/5/8 0008.
 */
public class MinIterator implements Iterattor {
    private List<Employee> list;
    private int position;

    public MinIterator(List<Employee> list) {
        this.list = list;
    }

    @Override
    public boolean hasNext() {
        return !(position > list.size() -1 || list.get(position) == null);
    }

    @Override
    public Object next() {
        Employee e = list.get(position);
        position++;
        return e;
    }
}

//HuiIterator.java(部门B)

/**
 * Created by Administrator on 2016/5/8 0008.
 */
public class HuiIterator implements Iterattor {
    private Employee[] array;
    private int position;

    public HuiIterator(Employee[] array) {
        this.array = array;
    }

    @Override
    public boolean hasNext() {
        return !(position > array.length -1 || array[position] == null);
    }

    @Override
    public Object next() {
        Employee e = array[position];
        position++;
        return e;
    }
}

//Company.java

**
 * Created by Administrator on 2016/5/8 0008.
 */
public interface Company {
    /**
     * 返回一个迭代器对象
     * @return 迭代器对象
     * */
    Iterattor iterator();
}

//CompanyMin.java(部门A)

/**
 * Created by Administrator on 2016/5/8 0008.
 */
public class CompanyMin implements Company{
    private List<Employee> list = new ArrayList<>();

    public CompanyMin(){
        list.add(new Employee("小民",96,"男","程序猿"));
        list.add(new Employee("小芸",22,"女","测试"));
        list.add(new Employee("小方",18,"女","测试"));
        list.add(new Employee("可儿",21,"女","设计"));
        list.add(new Employee("朗情",19,"女","设计"));
    }

    public List<Employee> getEmployee(){
        return list;
    }


    /**
     * 新加的
     * */
    @Override
    public Iterattor iterator() {
        return new MinIterator(list);
    }


}


//CompanyHui.java(部分B)

/**
 * Created by Administrator on 2016/5/8 0008.
 */
public class CompanyHui implements Company {
    private Employee[] array = new Employee[3];

    public CompanyHui(){
        array[0] = new Employee("辉哥",108,"男","程序猿");
        array[1] = new Employee("小红",98,"男","测试");
        array[2] = new Employee("小辉",88,"男","测试");
    }

    public Employee[] getEmployee(){
        return array;
    }

    @Override
    public Iterattor iterator() {
        return new HuiIterator(array);
    }
}

//Boss.java

/**
 * Created by Administrator on 2016/5/8 0008.
 */
public class Boss {
    public static void main(String[] args){
        //这是老方法  缺点:查看不同部门的信息,我们都要在Boss类中增加一段遍历逻辑  这时候可以用迭代器实现,将遍历逻辑封装
//        CompanyMin min = new CompanyMin();
//        List minList = min.getEmployee();
//        for(int i=0;i<minList.size();i++){
//            System.out.println(minList.get(i).toString());
//        }
//
//        CompanyHui hui = new CompanyHui();
//        Employee[] huiArray = hui.getEmployee();
//        for(int i = 0;i<huiArray.length;i++){
//            System.out.println(huiArray[i]);
//        }

        //这是新方法
        CompanyMin min = new CompanyMin();
        check(min.iterator());
        CompanyHui hui = new CompanyHui();
        check(hui.iterator());
    }
    private static void check(Iterattor iterator){
        while(iterator.hasNext()){
            System.out.println(iterator.next().toString());
        }
    }
}


7Android源码中的模式实现

1.除了各种数据结构体,如List,Map等包含的迭代器外

2.Android自身源码中也为我们提供了迭代器遍历数据,最为典型的例子就是数据库查询使用Cursor(当我们使用SQLiteDatabasequery方法查询数据库时返回的),该游标对象实质就是一个具体的迭代器,我们可以使用它来遍历数据库查询所得的结果集

 

 

8.优缺点

对于迭代模式来说,其自身优点很明显也很单一,支持以不同的方式去遍历一个容器对象,也可以有多个遍历,弱化了容器类与遍历算法之间的关系,而缺点就是对类文件的增加。

对于开发者而言,已经极少会去由自己来实现迭代器,因此,对于本章的内容更多地是在于了解而非应用









Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐