Android編程設(shè)計模式之迭代器模式詳解
本文實例講述了Android編程設(shè)計模式之迭代器模式。分享給大家供大家參考,具體如下:
一、介紹
迭代器模式(Iterator Pattern)又稱為游標(Cursor)模式,是行為型設(shè)計模式之一。迭代器模式算是一個比較古老的設(shè)計模式,其源于對容器的訪問,比如Java中的List、Map、數(shù)組等,我們知道對容器對象的訪問必然會涉及遍歷算法,我們可以將遍歷的方法封裝在容器中,或者不提供遍歷方法。如果我們將遍歷的方法封裝到容器中,那么對于容器類來說就承擔(dān)了過多的功能,容器類不僅要維護自身內(nèi)部的數(shù)據(jù)元素而且還要對外提供遍歷的接口方法,因為遍歷狀態(tài)的存儲問題還不能對同一個容器同時進行多個遍歷操作,如果我們不提供遍歷方法而讓使用者自己去實現(xiàn),又會讓容器的內(nèi)部細節(jié)暴露無遺,正因于此,迭代模式應(yīng)運而生,在客戶訪問類與容器體之間插入了一個第三者——迭代器,很好地解決了上面所述的弊端。
二、定義
提供一種方法順序訪問一個容器對象中的各個元素,而又不需要暴露該對象的內(nèi)部表示。
三、使用場景
遍歷一個容器對象。
四、迭代器模式的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:迭代器接口,迭代器接口負責(zé)定義、訪問和遍歷元素的接口。
ConcreteIterator:具體迭代器類,具體迭代器類的目的主要是實現(xiàn)迭代器接口,并記錄遍歷的當前位置。
Aggregate:容器接口,容器接口負責(zé)提供創(chuàng)建具體迭代器角色的接口。
ConcreteAggregate:具體容器類,具體迭代器角色與該容器相關(guān)聯(lián)。
Client:客戶類。
五、簡單實現(xiàn)
小民和小輝分別在公司的兩個事業(yè)部,某天老板安排任務(wù)讓他們倆統(tǒng)計一下各自部門的員工數(shù)據(jù),這很好辦嘛,建一個類用數(shù)據(jù)結(jié)構(gòu)把所有員工數(shù)據(jù)存進去即可,老板要看的時候給他用for循環(huán)實現(xiàn),還是比較容易的,下面就先為員工創(chuàng)建一個實體類:
員工實體類:
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, "女", "設(shè)計"));
list.add(new Employee("朗情", 19, "女", "設(shè)計")); //吐槽一下,為什么就小民一個男的,小輝部門全男的。
}
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)部實現(xiàn)是兩種方式,小民的人員信息容器的內(nèi)部實質(zhì)是使用的一個List類存儲人員信息,而小輝的實質(zhì)上使用的是一個數(shù)組,如果老板要查看人員信息就必須遍歷兩個容器:
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='測試'}
Employee{name='小方', age=18, sex=女, position='測試'}
Employee{name='可兒', age=21, sex=女, position='設(shè)計'}
Employee{name='朗情', age=19, sex=女, position='設(shè)計'}
這樣看似也沒有問題,但是如果有多個部門,每個部門有各自的實現(xiàn),那么我們就要在Boss類中增加一遍遍歷邏輯,這樣Boss類的功能會越來越多,同時暴露了內(nèi)部細節(jié)。那么我們需要定義一個迭代器接口:
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, "女", "設(shè)計"));
list.add(new Employee("朗情", 19, "女", "設(shè)計"));
}
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方法查詢數(shù)據(jù)庫時,會返回一個Cursor游標對象,該游標的實質(zhì)就是一個具體的迭代器,我們可以使用它來遍歷數(shù)據(jù)庫查詢所得的結(jié)果集。
七、總結(jié)
迭代器模式發(fā)展至今,幾乎所有的高級語言都有相應(yīng)的內(nèi)置實現(xiàn),對于開發(fā)者而言,已經(jīng)極少會自己去實現(xiàn)迭代器了,所以本章內(nèi)容更多的是了解而非應(yīng)用。
優(yōu)點:
符合面向?qū)ο笤O(shè)計原則中的單一職責(zé)原則。
支持對容器對象的多種遍歷。弱化了容器類與遍歷算法之間的關(guān)系。
缺點:
類文件的增加。
會出現(xiàn)ConcurrentModificationException異常。
遍歷過程是一個單向且不可逆的遍歷。
更多關(guān)于Android相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Android開發(fā)入門與進階教程》、《Android調(diào)試技巧與常見問題解決方法匯總》、《Android基本組件用法總結(jié)》、《Android視圖View技巧總結(jié)》、《Android布局layout技巧總結(jié)》及《Android控件用法總結(jié)》
希望本文所述對大家Android程序設(shè)計有所幫助。
相關(guān)文章
Android樣式的開發(fā):layer-list實例詳解
本文主要介紹Android樣式開發(fā)layer-list,這里整理了詳細的資料,及簡單示例代碼有興趣的小伙伴可以參考下2016-09-09
Android依據(jù)名字通過反射獲取在drawable中的圖片
依據(jù)圖片的名字,通過反射獲取其在drawable中的ID,在根據(jù)此ID顯示圖片,具體實現(xiàn)如下,感興趣的朋友可以參考下哈2013-06-06
Android界面 NotificationManager使用Bitmap做圖標
Android界面 NotificationManager使用Bitmap做圖標,如何實現(xiàn)呢,本文將介紹解決方法,需要的朋友可以參考下2012-12-12
Android將應(yīng)用調(diào)試log信息保存在SD卡的方法
Android將應(yīng)用調(diào)試log信息保存在SD卡的方法大家都知道嗎,下面腳本之家小編給大家分享Android將應(yīng)用調(diào)試log信息保存在SD卡的方法,感興趣的朋友參考下2016-04-04
Android判斷touch事件點是否在view范圍內(nèi)的方法
這篇文章主要介紹了Android判斷touch事件點是否在view范圍內(nèi)的方法,涉及Android事件響應(yīng)與view屬性操作的相關(guān)技巧,需要的朋友可以參考下2016-03-03
android ListView和GridView拖拽移位實現(xiàn)代碼
有些朋友對android中ListView和GridView拖拽移位功能的實現(xiàn)不是很了解,接下來將詳細介紹,需要了解的朋友可以參考下2012-12-12
Android開發(fā)listview選中高亮簡單實現(xiàn)代碼分享
這篇文章主要介紹了Android開發(fā)listview選中高亮簡單實現(xiàn)代碼分享,具有一定借鑒價值,需要的朋友可以參考下2018-01-01
Ubutu1604安裝colmap實現(xiàn)方法詳細教程
這篇文章主要介紹了Ubutu1604安裝colmap實現(xiàn)方法詳細教程,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-11-11

