Android编程设计模式之迭代器模式详解

本文实例讲述了Android编程设计模式之迭代器模式。分享给大家供大家参考,具体如下:

一、介绍

迭代器模式(Iterator Pattern)又称为游标(Cursor)模式,是行为型设计模式之一。迭代器模式算是一个比较古老的设计模式,其源于对容器的访问,比如Java中的List、Map、数组等,我们知道对容器对象的访问必然会涉及遍历算法,我们可以将遍历的方法封装在容器中,或者不提供遍历方法。如果我们将遍历的方法封装到容器中,那么对于容器类来说就承担了过多的功能,容器类不仅要维护自身内部的数据元素而且还要对外提供遍历的接口方法,因为遍历状态的存储问题还不能对同一个容器同时进行多个遍历操作,如果我们不提供遍历方法而让使用者自己去实现,又会让容器的内部细节暴露无遗,正因于此,迭代模式应运而生,在客户访问类与容器体之间插入了一个第三者——迭代器,很好地解决了上面所述的弊端。

二、定义

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

三、使用场景

遍历一个容器对象。

四、迭代器模式的UML类图

UML类图:

通用模式代码:

迭代器接口:

public interface Iterator<T> {
  /**
   * 是否还有下一个元素
   * @return true表示有,false表示没有
   **/
  boolean hasNext();
  /**
   * 返回当前位置的元素并将位置移至下一位
   **/
  T next();
}

具体迭代器类:

public class ConcreteIterator<T> implements Iterator<T>{
  private List<T> list;
  private int cursor = 0;
  public ConcreteIterator(List<T> list) {
    this.list = list;
  }
  @Override
  public boolean hasNext() {
    return cursor != list.size();
  }
  @Override
  public T next() {
    T obj = null;
    if (this.hasNext()) {
      obj = this.list.get(cursor++);
    }
    return obj;
  }
}

容器接口:

public interface Aggregation<T> {
  /**
   * 添加一个元素
   **/
  void add(T obj);
  /**
   * 移除一个元素
   **/
  void remove(T obj);
  /**
   * 获取容器的迭代器
   **/
  Iterator<T> iterator();
}

具体容器类:

public class ConcreteAggregation<T> implements Aggregation<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<>(list);
  }
}

客户类:

public class Client {
  public static void main(String args[]) {
    Aggregation<String> a = new ConcreteAggregation<>();
    a.add("a");
    a.add("b");
    a.add("c");
    Iterator<String> iterator = a.iterator();
    while (iterator.hasNext()) {
      System.out.print(iterator.next());
    }
  }
}

角色介绍:

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

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

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

ConcreteAggregate:具体容器类,具体迭代器角色与该容器相关联。

Client:客户类。

五、简单实现

小民和小辉分别在公司的两个事业部,某天老板安排任务让他们俩统计一下各自部门的员工数据,这很好办嘛,建一个类用数据结构把所有员工数据存进去即可,老板要看的时候给他用for循环实现,还是比较容易的,下面就先为员工创建一个实体类:

员工实体类:

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) {
    super();
    this.name = name;
    this.age = age;
    this.sex = sex;
    this.position = position;
  }
  // 简化代码,省略setter和getter方法
  @Override
  public String toString() {
    return "Employee{" + "name='" + name + '\'' + ", age=" + age + ", sex="
        + sex + ", position='" + position + '\'' + "}";
  }
}

小民部门:

public class CompanyMin {
  private List<Employee> list = new ArrayList<>();
  public CompanyMin(){
    list.add(new Employee("小民", 26, "男", "程序猿"));
    list.add(new Employee("小芸", 22, "女", "测试"));
    list.add(new Employee("小方", 18, "女", "测试"));
    list.add(new Employee("可儿", 21, "女", "设计"));
    list.add(new Employee("朗情", 19, "女", "设计")); //吐槽一下,为什么就小民一个男的,小辉部门全男的。
  }
  public List<Employee> getEmployees(){
    return list;
  }
}

小辉部门:

public class CompanyHui {
private Employee[] array = new Employee[3];
  public CompanyHui(){
    array[0] = new Employee("辉哥", 28, "男", "程序猿");
    array[1] = new Employee("小红", 23, "男", "程序猿");
    array[2] = new Employee("小辉", 25, "男", "程序猿");
  }
  public Employee[] getEmployees(){
    return array;
  }
}

可见小民和小辉的内部实现是两种方式,小民的人员信息容器的内部实质是使用的一个List类存储人员信息,而小辉的实质上使用的是一个数组,如果老板要查看人员信息就必须遍历两个容器:

Boss查看:

public class Boss {
  public static void main(String[] args) {
    CompanyHui hui = new CompanyHui();
    Employee[] huiList = hui.getEmployees();
    for(int i = 0; i < huiList.length; i++){
      System.out.println(huiList[i]);
    }
    CompanyMin min = new CompanyMin();
    List minList = min.getEmployees();
    for(int i = 0; i < minList.size(); i++){
      System.out.println(minList.get(i).toString());
    }
  }
}

结果:

Employee{name='辉哥', age=28, sex=男, position='程序猿'}
Employee{name='小红', age=23, sex=男, position='程序猿'}
Employee{name='小辉', age=25, sex=男, position='程序猿'}
Employee{name='小民', age=26, sex=男, position='程序猿'}
Employee{name='小芸', age=22, sex=女, position='测试'}
Employee{name='小方', age=18, sex=女, position='测试'}
Employee{name='可儿', age=21, sex=女, position='设计'}
Employee{name='朗情', age=19, sex=女, position='设计'}

这样看似也没有问题,但是如果有多个部门,每个部门有各自的实现,那么我们就要在Boss类中增加一遍遍历逻辑,这样Boss类的功能会越来越多,同时暴露了内部细节。那么我们需要定义一个迭代器接口:

public interface Iterator {
  /**
   * 是否还有下一个元素
   *
   * @return true表示有,false表示没有
   */
  boolean hasNext();
  /**
   * 返回当前元素,并将位置移至下一位
   */
  Object next();
}

小民的迭代器:

public class MinIterator implements Iterator{
  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;
  }
}

小辉的迭代器:

public class HuiIterator implements Iterator{
  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;
  }
}

定义容器类的接口:

public interface Company {
  /**
   * 返回一个迭代器对象
   *
   * @return 迭代器对象
   */
  Iterator iterator();
}

修改一下之前的两个容器类:

public class CompanyHui implements Company{
  private Employee[] array = new Employee[3];
  public CompanyHui(){
    array[0] = new Employee("辉哥", 28, "男", "程序猿");
    array[1] = new Employee("小红", 23, "男", "程序猿");
    array[2] = new Employee("小辉", 25, "男", "程序猿");
  }
  public Employee[] getEmployees(){
    return array;
  }
  @Override
  public Iterator iterator() {
    return new HuiIterator(array);
  }
}
public class CompanyMin implements Company{
  private List<Employee> list = new ArrayList<>();
  public CompanyMin(){
    list.add(new Employee("小民", 26, "男", "程序猿"));
    list.add(new Employee("小芸", 22, "女", "测试"));
    list.add(new Employee("小方", 18, "女", "测试"));
    list.add(new Employee("可儿", 21, "女", "设计"));
    list.add(new Employee("朗情", 19, "女", "设计"));
  }
  public List<Employee> getEmployees(){
    return list;
  }
  @Override
  public Iterator iterator() {
    return new MinIterator(list);
  }
}

Boss查看:

public class Boss {
  public static void main(String[] args) {
    CompanyHui hui = new CompanyHui();
    check(hui.iterator());
    CompanyMin min = new CompanyMin();
    check(min.iterator());
  }
  private static void check(Iterator iterator){
    while (iterator.hasNext()) {
      System.out.println(iterator.next().toString());
    }
  }
}

六、Android源码中的迭代器模式

1、Cursor

当我们使用SQLiteDatabase的query方法查询数据库时,会返回一个Cursor游标对象,该游标的实质就是一个具体的迭代器,我们可以使用它来遍历数据库查询所得的结果集。

七、总结

迭代器模式发展至今,几乎所有的高级语言都有相应的内置实现,对于开发者而言,已经极少会自己去实现迭代器了,所以本章内容更多的是了解而非应用。

优点:

符合面向对象设计原则中的单一职责原则。

支持对容器对象的多种遍历。弱化了容器类与遍历算法之间的关系。

缺点:

类文件的增加。

会出现ConcurrentModificationException异常。

遍历过程是一个单向且不可逆的遍历。

更多关于Android相关内容感兴趣的读者可查看本站专题:《Android开发入门与进阶教程》、《Android调试技巧与常见问题解决方法汇总》、《Android基本组件用法总结》、《Android视图View技巧总结》、《Android布局layout技巧总结》及《Android控件用法总结》

希望本文所述对大家Android程序设计有所帮助。

(0)

相关推荐

  • Android编程设计模式之责任链模式详解

    本文实例讲述了Android编程设计模式之责任链模式.分享给大家供大家参考,具体如下: 一.介绍 责任链模式(Iterator Pattern),是行为型设计模式之一.什么是"链"?我们将多个节点首尾相连所构成的模型称为链,比如生活中常见的锁链,就是由一个个圆角长方形的铁环串起来的结构.对于链式结构,每个节点都可以被拆开再连接,因此,链式结构也具有很好的灵活性.将这样一种结构应用于编程领域,将每一个节点看作是一个对象,每一个对象拥有不同的处理逻辑,将一个请求从链式的首端发出,沿着链的路

  • Android编程设计模式之解释器模式详解

    本文实例讲述了Android编程设计模式之解释器模式.分享给大家供大家参考,具体如下: 一.介绍 解释器模式(Interpreter Pattern)是一种用的比较少的行为型模式,其提供了一种解释语言的语法或表达式的方式,该模式定义了一个表达式接口,通过该接口解释一个特定的上下文.在这么多的设计模式中,解释器模式在实际运用上相对来说要少很多,因为我们很少会自己去构造一个语言的文法.虽然如此,既然它能够在设计模式中有一席之位,那么必定有它的可用之处. 二.定义 给定一个语言,定义它的文法的一种表示

  • Android编程设计模式之抽象工厂模式详解

    本文实例讲述了Android编程设计模式之抽象工厂模式.分享给大家供大家参考,具体如下: 一.介绍 抽象工厂模式(Abstract Factory Pattern),也是创建型设计模式之一.前一节我们已经了解了工厂方法模式,那么这个抽象工厂又是怎么一回事呢?大家联想一下现实生活中的工厂肯定都是具体的,也就是说每个工厂都会生产某一种具体的产品,那么抽象工厂意味着生产出来的产品是不确定的,那这岂不是很奇怪?抽象工厂模式起源于以前对不同操作系统的图形化解决方案,如不同操作系统中的按钮和文本框控件其实现

  • Android编程设计模式之策略模式详解

    本文实例讲述了Android编程设计模式之策略模式.分享给大家供大家参考,具体如下: 一.介绍 在软件开发中也常常遇到这样的情况:实现某一个功能可以有多种算法或者策略,我们根据实际情况选择不同的算法或者策略来完成该功能.例如,排序算法,可以使用插入排序.归并排序.冒泡排序等. 针对这种情况,一种常规的方法是将多种算法写在一个类中.例如,需要提供多种排序算法,可以将这些算法写到一个类中,每一个方法对应一个具体的排序算法:当然,也可以将这些排序算法封装在一个统一的方法中,通过if-else-或者ca

  • android设计模式之单例模式详解

    这是我们最常见的一类模式,对这一类模式有一个通用的特点就是: 封装创建的方式和过程. 这里所谓封装就是隐藏的意思,对对象的创建方法和过程不可见,或者是虚拟的过程. 隐藏创建方式,就是如单例,工厂方法,隐藏创建过程则是指builder,原型,至于抽象工厂,我认为他包含了以上两种. 我们想想一个对象的创建有哪些步骤? 1.创建什么东西?--接口定义 2.谁创建?        --决策类or帮助类 3.如何创建?     --how,创建过程 4.什么时候创建?    --创建时机的触发 由此可知,

  • Android编程设计模式之状态模式详解

    本文实例讲述了Android编程设计模式之状态模式.分享给大家供大家参考,具体如下: 一.介绍 状态模式中的行为是由状态来决定的,不同的状态下有不同的行为.状态模式和策略模式的结构几乎完全一样,但它们的目的.本质却完全不一样.状态模式的行为是平行的.不可替换的,策略模式的行为是彼此独立.可相互替换的.用一句话来表述,状态模式把对象的行为包装在不同的状态对象里,每一个状态对象都有一个共同的抽象状态基类.状态模式的意图是让一个对象在其内部状态改变的时候,其行为也随之改变. 二.定义 当一个对象的内在

  • Android编程设计模式之备忘录模式详解

    本文实例讲述了Android编程设计模式之备忘录模式.分享给大家供大家参考,具体如下: 一.介绍 备忘录模式是一种行为模式,该模式用于保存对象当前状态,并且在之后可以再次恢复到此状态,这有点像我们平时说的"后悔药".备忘录模式实现的方式需要保证被保存的对象状态不能被对象从外部访问,目的是为了保护好被保存的这些对象状态的完整性以及内部实现不向外暴露. 二.定义 在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样,以后就可将该对象恢复到原先保存的状态. 三.使用

  • Android编程设计模式之中介者模式详解

    本文实例讲述了Android编程设计模式之中介者模式.分享给大家供大家参考,具体如下: 一.介绍 中介者模式(Mediator Pattern)也称为调解者模式或调停者模式,Mediator本身就有调停者和调解者的意思. 在日常生活中调停者或调解者这个角色我们见得比较多的是"和事老",也就是说调解两个有争端的人的角色,举个不恰当的例子,比如爸妈吵架,孩子或者双方父母则会出面劝架或阻止争吵,这里孩子或双方父母则是充当的是调解者的模式. 而对于中介呢?大家平时听得最多的莫过于房产中介了,在

  • Android编程设计模式之命令模式详解

    本文实例讲述了Android编程设计模式之命令模式.分享给大家供大家参考,具体如下: 一.介绍 命令模式(Command Pattern),是行为型设计模式之一.命令模式相对于其他的设计模式来说并没有那么多的条条框框,其实它不是一个很"规范"的模式,不过,就是基于这一点,命令模式相对于其他的设计模式更为灵活多变.我们接触比较多的命令模式个例无非就是程序菜单命令,如在操作系统中,我们点击"关机"命令,系统就会执行一系列的操作,如先是暂停处理事件,保存系统的一些配置,然

  • Android编程设计模式之访问者模式详解

    本文实例讲述了Android编程设计模式之访问者模式.分享给大家供大家参考,具体如下: 一.介绍 访问者模式是一种将数据操作与数据结构分离的设计模式,它是<设计模式>中23种设计模式中最复杂的一个,但它的使用频率并不高,正如<设计模式>的作者GOF对访问者模式的描述:大多数情况下,你不需要使用访问者模式,但是当你一旦需要使用它时,那你就是真的需要它了. 访问者模式的基本想法是,软件系统中拥有一个由许多对象构成的.比较稳定的对象结构,这些对象的类都拥有一个accept方法用来接受访问

  • Android编程设计模式之模板方法模式详解

    本文实例讲述了Android编程设计模式之模板方法模式.分享给大家供大家参考,具体如下: 一.介绍 在面向对象开发过程中,通常会遇到这样的一个问题,我们知道一个算法所需的关键步骤,并确定了这些步骤的执行顺序,但是,某些步骤的具体实现是未知的,或者说某些步骤的实现是会随着环境的变化而改变的,例如,执行程序的流程大致如下: 1.检查代码的正确性: 2.链接相关的类库: 3.编译相关代码: 4.执行程序. 对于不同的程序设计语言,上述4个步骤都是不一样的,但是,它们的执行流程是固定的,这类问题的解决方

随机推荐