溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Android中怎么實(shí)現(xiàn)迭代器模式

發(fā)布時(shí)間:2021-06-29 15:41:40 來源:億速云 閱讀:118 作者:Leah 欄目:移動(dòng)開發(fā)

這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)碛嘘P(guān)Android中怎么實(shí)現(xiàn)迭代器模式,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

一、介紹

迭代器模式(Iterator Pattern)又稱為游標(biāo)(Cursor)模式,是行為型設(shè)計(jì)模式之一。迭代器模式算是一個(gè)比較古老的設(shè)計(jì)模式,其源于對(duì)容器的訪問,比如Java中的List、Map、數(shù)組等,我們知道對(duì)容器對(duì)象的訪問必然會(huì)涉及遍歷算法,我們可以將遍歷的方法封裝在容器中,或者不提供遍歷方法。如果我們將遍歷的方法封裝到容器中,那么對(duì)于容器類來說就承擔(dān)了過多的功能,容器類不僅要維護(hù)自身內(nèi)部的數(shù)據(jù)元素而且還要對(duì)外提供遍歷的接口方法,因?yàn)楸闅v狀態(tài)的存儲(chǔ)問題還不能對(duì)同一個(gè)容器同時(shí)進(jìn)行多個(gè)遍歷操作,如果我們不提供遍歷方法而讓使用者自己去實(shí)現(xiàn),又會(huì)讓容器的內(nèi)部細(xì)節(jié)暴露無遺,正因于此,迭代模式應(yīng)運(yùn)而生,在客戶訪問類與容器體之間插入了一個(gè)第三者——迭代器,很好地解決了上面所述的弊端。

二、定義

提供一種方法順序訪問一個(gè)容器對(duì)象中的各個(gè)元素,而又不需要暴露該對(duì)象的內(nèi)部表示。

三、使用場(chǎng)景

遍歷一個(gè)容器對(duì)象。

四、迭代器模式的UML類圖

UML類圖:

Android中怎么實(shí)現(xiàn)迭代器模式

通用模式代碼:

迭代器接口:

public interface Iterator<T> {
  /**
   * 是否還有下一個(gè)元素
   * @return true表示有,false表示沒有
   **/
  boolean hasNext();
  /**
   * 返回當(dāng)前位置的元素并將位置移至下一位
   **/
  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> {
  /**
   * 添加一個(gè)元素
   **/
  void add(T obj);
  /**
   * 移除一個(gè)元素
   **/
  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:迭代器接口,迭代器接口負(fù)責(zé)定義、訪問和遍歷元素的接口。

ConcreteIterator:具體迭代器類,具體迭代器類的目的主要是實(shí)現(xiàn)迭代器接口,并記錄遍歷的當(dāng)前位置。

Aggregate:容器接口,容器接口負(fù)責(zé)提供創(chuàng)建具體迭代器角色的接口。

ConcreteAggregate:具體容器類,具體迭代器角色與該容器相關(guān)聯(lián)。

Client:客戶類。

五、簡(jiǎn)單實(shí)現(xiàn)

小民和小輝分別在公司的兩個(gè)事業(yè)部,某天老板安排任務(wù)讓他們倆統(tǒng)計(jì)一下各自部門的員工數(shù)據(jù),這很好辦嘛,建一個(gè)類用數(shù)據(jù)結(jié)構(gòu)把所有員工數(shù)據(jù)存進(jìn)去即可,老板要看的時(shí)候給他用for循環(huán)實(shí)現(xiàn),還是比較容易的,下面就先為員工創(chuàng)建一個(gè)實(shí)體類:

員工實(shí)體類:

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;
  }
  // 簡(jiǎn)化代碼,省略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, "女", "測(cè)試"));
    list.add(new Employee("小方", 18, "女", "測(cè)試"));
    list.add(new Employee("可兒", 21, "女", "設(shè)計(jì)"));
    list.add(new Employee("朗情", 19, "女", "設(shè)計(jì)")); //吐槽一下,為什么就小民一個(gè)男的,小輝部門全男的。
  }
  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;
  }
}

可見小民和小輝的內(nèi)部實(shí)現(xiàn)是兩種方式,小民的人員信息容器的內(nèi)部實(shí)質(zhì)是使用的一個(gè)List類存儲(chǔ)人員信息,而小輝的實(shí)質(zhì)上使用的是一個(gè)數(shù)組,如果老板要查看人員信息就必須遍歷兩個(gè)容器:

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

結(jié)果:

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='測(cè)試'}
Employee{name='小方', age=18, sex=女, position='測(cè)試'}
Employee{name='可兒', age=21, sex=女, position='設(shè)計(jì)'}
Employee{name='朗情', age=19, sex=女, position='設(shè)計(jì)'}

這樣看似也沒有問題,但是如果有多個(gè)部門,每個(gè)部門有各自的實(shí)現(xiàn),那么我們就要在Boss類中增加一遍遍歷邏輯,這樣Boss類的功能會(huì)越來越多,同時(shí)暴露了內(nèi)部細(xì)節(jié)。那么我們需要定義一個(gè)迭代器接口:

public interface Iterator {
  /**
   * 是否還有下一個(gè)元素
   *
   * @return true表示有,false表示沒有
   */
  boolean hasNext();
  /**
   * 返回當(dāng)前元素,并將位置移至下一位
   */
  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 {
  /**
   * 返回一個(gè)迭代器對(duì)象
   *
   * @return 迭代器對(duì)象
   */
  Iterator iterator();
}

修改一下之前的兩個(gè)容器類:

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, "女", "測(cè)試"));
    list.add(new Employee("小方", 18, "女", "測(cè)試"));
    list.add(new Employee("可兒", 21, "女", "設(shè)計(jì)"));
    list.add(new Employee("朗情", 19, "女", "設(shè)計(jì)"));
  }
  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

當(dāng)我們使用SQLiteDatabase的query方法查詢數(shù)據(jù)庫(kù)時(shí),會(huì)返回一個(gè)Cursor游標(biāo)對(duì)象,該游標(biāo)的實(shí)質(zhì)就是一個(gè)具體的迭代器,我們可以使用它來遍歷數(shù)據(jù)庫(kù)查詢所得的結(jié)果集。

七、總結(jié)

迭代器模式發(fā)展至今,幾乎所有的高級(jí)語言都有相應(yīng)的內(nèi)置實(shí)現(xiàn),對(duì)于開發(fā)者而言,已經(jīng)極少會(huì)自己去實(shí)現(xiàn)迭代器了,所以本章內(nèi)容更多的是了解而非應(yīng)用。

優(yōu)點(diǎn):

符合面向?qū)ο笤O(shè)計(jì)原則中的單一職責(zé)原則。

支持對(duì)容器對(duì)象的多種遍歷。弱化了容器類與遍歷算法之間的關(guān)系。

缺點(diǎn):

類文件的增加。

會(huì)出現(xiàn)ConcurrentModificationException異常。

遍歷過程是一個(gè)單向且不可逆的遍歷。

上述就是小編為大家分享的Android中怎么實(shí)現(xiàn)迭代器模式了,如果剛好有類似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI