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

通用模式代碼:
迭代器接口:
public interface Iterator<T> { /** * 是否還有下一個(gè)元素 * @return true表示有,false表示沒(méi)有 **/ 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é)定義、訪問(wèn)和遍歷元素的接口。
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; }}可見(jiàn)小民和小輝的內(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ì)'}這樣看似也沒(méi)有問(wèn)題,但是如果有多個(gè)部門,每個(gè)部門有各自的實(shí)現(xiàn),那么我們就要在Boss類中增加一遍遍歷邏輯,這樣Boss類的功能會(huì)越來(lái)越多,同時(shí)暴露了內(nèi)部細(xì)節(jié)。那么我們需要定義一個(gè)迭代器接口:
public interface Iterator { /** * 是否還有下一個(gè)元素 * * @return true表示有,false表示沒(méi)有 */ 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è)具體的迭代器,我們可以使用它來(lái)遍歷數(shù)據(jù)庫(kù)查詢所得的結(jié)果集。
七、總結(jié)
迭代器模式發(fā)展至今,幾乎所有的高級(jí)語(yǔ)言都有相應(yīng)的內(nèi)置實(shí)現(xiàn),對(duì)于開(kāi)發(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異常。
遍歷過(guò)程是一個(gè)單向且不可逆的遍歷。
更多關(guān)于Android相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Android開(kāi)發(fā)入門與進(jìn)階教程》、《Android調(diào)試技巧與常見(jiàn)問(wèn)題解決方法匯總》、《Android基本組件用法總結(jié)》、《Android視圖View技巧總結(jié)》、《Android布局layout技巧總結(jié)》及《Android控件用法總結(jié)》
希望本文所述對(duì)大家Android程序設(shè)計(jì)有所幫助。
新聞熱點(diǎn)
疑難解答
圖片精選