设计模式之--迭代器模式
一、迭代器模式介绍
迭代器模式(Iterator Pattern)又称为(Cursor)模式,是行为设计模式之一。迭代器模式算是一个比较古老的设计模式,其源于对容器的访问,比如Java 中的 List、Map、数组等,我们知道对容器对象的访问必然会涉及遍历算法,我们可以将遍历的方法封装在容器中,或者不提供遍历方法。如果我们将遍历的方法封装到容器中,那么对于容器来说就承担了过多的功能,容器类不仅要维护自身内部的数据元素而且还要对外提供遍历的接口方法,因为遍历状态的存储问题还不能对同一个容器同时进行多个遍历操作,如果我们不提供遍历方法而让使用者自己去实现,又会让容器的内部细节暴露无遗,正因为于此,迭代模式应用而生,在客户访问类与容器体之间插入了一个第三者–迭代器,很好的解决了上面所述的弊端。
二、迭代器模式的定义
提供一种方法顺序访问一个容器对象中的各个元素,而又不需要暴露该对象的内部表示。
三、迭代器模式的使用场景
遍历一个容器对象时。
四、迭代器模式的UML类图
根据类图可以得出如下一个迭代器模式的通用模式代码。
//1、迭代器接口
public interface Iterator<T> {/*** 是否还有下一个元素* @return true 表示有,false 表示没有*/boolean hasNext();/*** 返回当前位置的元素并将位置移至下一位* @return*/T next();
}
//2、具体迭代器类
public class ConcreteIterator<T> implements Iterator<T> {private List<T> list = new ArrayList<T>();private int cursor = 0;public ConcreteIterator(List<T> list) {this.list = list;}@Overridepublic boolean hasNext() {return cursor != list.size();}@Overridepublic T next() {T obj = null;if (this.hasNext()) {obj = this.list.get(cursor++);}return obj;}}
//3、容器接口
public interface Aggregate<T> {/*** 添加一个元素* @param obj 元素对象*/void add(T obj);/*** 移除一个元素* @param obj*/void remove(T obj);/*** 获取容器的迭代器* @return*/Iterator<T> iterator();}
//4、具体容器类
public class ConcreteAggregate<T> implements Aggregate<T> {private List<T> list = new ArrayList<T>();@Overridepublic void add(T obj) {list.add(obj);}@Overridepublic void remove(T obj) {list.remove(obj);}@Overridepublic Iterator<T> iterator() {return new ConcreteIterator<T>(list);}}
//5、客户类
public class Client {public static void main(String[] args) {Aggregate<String> a = new ConcreteAggregate<>();a.add("Aige");a.add("Studio");a.add("SM");a.add("Brother");Iterator<String> i = a.iterator();while (i.hasNext()) {System.out.println(i.next());}}
}
运行结果:
角色介绍:
1、Iterator: 迭代器接口。
迭代器接库负责定义、访问和遍历元素的接口。
2、ConcreteIterator:具体迭代器类。
具体迭代器类的目的主要是实现迭代器接口,并记录遍历的当前位置。
3、Aggregate: 容器接口。
容器接口负责提供创建具体迭代器角色的接口。
4、ConcreteAggregate:具体容器类。
具体迭代器角色与该容器相关联。
5、Client: 客户类。
五、迭代器模式的简单实现
小明和小辉分别在公司的两个事业部,老板安排任务,让他们俩统计一下各自部门的员工数据。
先为员工创建一个实体类:
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;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public String getPosition() {return position;}public void setPosition(String position) {this.position = position;}@Overridepublic String toString() {return "Employee [name=" + name + ", age=" + age + ", sex=" + sex + ", position=" + position + "]";}
}
定义一个迭代器接口:
public interface Iterator {/*** 是否还有下一个元素* @return true 表示有,false 表示没有*/boolean hasNext();/*** 返回当前位置的元素,并将位置移至下一位* @return*/Object next();
}
对于小明和小辉部门的人员信息容器,我们分别创建一个对应的迭代器:
public class MinIterator implements Iterator {private List<Employee> list;private int position;public MinIterator(List<Employee> list) {this.list = list;}@Overridepublic boolean hasNext() {return !(position > list.size() - 1 || list.get(position) == null);}@Overridepublic Object next() {Employee employee = list.get(position);position++;return employee;}
}
同时,我们定义一个容器类的接口,在该接口中定义一个能够返回容器迭代器的方法:
public interface Company {/*** 返回一个迭代器对象* @return 迭代器对象*/Iterator iterator();}
这时给出两个容器类使之实现容器接口,并返回对应的迭代器对象:
小明和小辉两个部门间人员数据的构建,对于小明的部门,小明创建一个 CompanyMin 类来存储人员信息,这里为了简化代码,我们不提供对外添加人员信息的add方法,只在构造方法中固定数据:
public class CompanyMin implements Company {private List<Employee> list = new ArrayList<>();public CompanyMin() {list.add(new Employee("小明", 26, "男", "程序员"));list.add(new Employee("小云", 26, "女", "测试"));list.add(new Employee("小方", 26, "女", "测试"));list.add(new Employee("可儿", 26, "女", "运营"));list.add(new Employee("安琪拉", 26, "女", "设计"));}public List<Employee> getEmployee(){return list;}@Overridepublic Iterator iterator() {return new MinIterator(list); }}
而对于小辉,同样也创建了一个CompanyHui类作为容器:
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[] getEmployees(){return array;}@Overridepublic Iterator iterator() {return new HuiIterator(array);}
}
最后在Boss 类中查阅人员的信息将变得更简单:
public class Boss {public static void main(String[] args) {CompanyMin min = new CompanyMin();check(min.iterator());System.out.println("====================");CompanyHui hui = new CompanyHui();check(hui.iterator());}private static void check(Iterator iterator) {while (iterator.hasNext()) {System.out.println(iterator.next().toString());}}}
运行结果:
其实,在上述例子中只是做了一个假设,在所谓的自定义“容器”类中又使用了 Java 本身所提供的数据结构来存储数据,这也算是一种不恰当的实现方式,因为迭代器模式的规定不像其他模式那么严格,实现也因人而异,好在大部分高级语言的容器类都为我们提供了相应的迭代器而不需要开发者去实现。
六、Android源码中的设计模式
迭代器这个模式对开发者来说几乎不会自己去实现一个迭代器,就拿Android来说吧,其除了各种数据结构体,如List 、Map 等所包含的迭代器外,Android自身源码中也为我们提供了迭代器遍历数据,最为典型的例子就是数据库查询使用Cursor,当我们使用SQLiteDatabase 的 query 方法查询数据库时,会返回一个Cursor 游标对象,该游标对象实质就是一个具体的迭代器,我们可以使用它来遍历数据库查询所得的结果集,这里给出一个简单的查询SQLite数据库的例子。首先定义一个SQLiteOpenHelper:
public class DBHelper extends SQLiteOpenHelper {public DBHelper(Context context) {super(context,"DB_AIGE",null,1);}@Overridepublic void onCreate(SQLiteDatabase db) {db.execSQL("CREATE TABLE table_aige(_id INTEGER PRIMARY KEY AUTOINCREMENT,name TEXT,sex TEXT)");db.execSQL("INSERT INTO table_aige(name,sex) values ('Aige','man')");db.execSQL("INSERT INTO table_aige(name,sex) values ('SMBrother','man')");}@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}
}
为了方便起见,直接在 onCreate 方法中创建表并直接插入了两条数据,同时,也是为了简便起见,就不再创建数据库操作相关的业务逻辑方法了,这里直接用一个 ContentProvider 来对数据库进行操作:
public class DataProvider extends ContentProvider {private DBHelper mDBHelper;@Overridepublic boolean onCreate() {mDBHelper = new DBHelper(getContext());return true;}@Nullable@Overridepublic Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection,@Nullable String[] selectionArgs, @Nullable String sortOrder) {SQLiteDatabase db = mDBHelper.getReadableDatabase();return db.query("table_aige",projection,null,null,null,null,null);}@Nullable@Overridepublic String getType(@NonNull Uri uri) {return null;}@Nullable@Overridepublic Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {return null;}@Overridepublic int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {return 0;}@Overridepublic int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {return 0;}
}
这里我们只实现了查询方法,其余均保持默认,当然,作为四大组件之一,我们还需要在AndroidManifest.xml文件中对该ContentProvider 进行声明:
<provider
android:name=".DataProvider"android:authorities="com.aigestudio.test.DataProvider" />
最后我们在Activity 中通过这个ContentProvider 查询数据库:
public class IteratorActivity extends ListActivity {private static final String[] PROJECTION = new String[]{"name","sex"};private static final Uri URI = Uri.parse("content://com.aigestudio.test.DataProvider/table_aige");@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);Cursor cursor = getContentResolver().query(URI,PROJECTION,null,null,null);List<Map<String,String>> list = new ArrayList<>();cursor.moveToFirst();do {Map<String,String> item = new HashMap<>();item.put("name",cursor.getString(0));item.put("sex",cursor.getString(1));list.add(item);}while (cursor.moveToNext());cursor.close();setListAdapter(new SimpleAdapter(this,list,android.R.layout.simple_list_item_2,new String[]{"name","sex"},new int[]{android.R.id.text1,android.R.id.text2}));}
}
具体的显示结果如下图:
七、总结
对于迭代模式来说,其自身优点明显也很单一,支持以不同的方式去遍历一个容器对象,也可以有多个遍历,弱化了容器类与遍历算法之间的关系,而其缺点就是对类文件的增加。
大家也可能会想到其他的语言,如 C++、Python、PHP等,他们内部也有众多容器体的定义,当然,也有相应的迭代器。迭代器模式发展至今,几乎每一种高级语言都有相应的内置实现,对于开发者而言,已经极少会去由自己来实现迭代器了,因此,对于本章的内容更多地是在于了解而非应用。
设计模式之--迭代器模式相关推荐
- 【GOF23设计模式】迭代器模式
[GOF23设计模式]迭代器模式 来源:http://www.bjsxt.com/ 一.[GOF23设计模式]_迭代器模式.JDK内置迭代器.内部类迭代器 1 package com.test.it ...
- [转载] Python进阶:设计模式之迭代器模式
参考链接: Python中的迭代器 在软件开发领域中,人们经常会用到这一个概念--"设计模式"(design pattern),它是一种针对软件设计的共性问题而提出的解决方案.在一 ...
- 每日学一个设计模式1——迭代器模式
引言 精通设计模式是从码农脱颖而出的条件之一.跟着<图解设计模式>这本书学习设计模式,从今天开始,一天总结一个设计模式. 迭代器模式(一个一个遍历) 用处 隐藏遍历集合的内部结构,遍历不同 ...
- php迭代器实例,php设计模式之迭代器模式实例分析【星际争霸游戏案例】
本文实例讲述了php设计模式之迭代器模式.分享给大家供大家参考,具体如下: 星际的任务关一般会有这样的设定:一开始电脑的农民不采矿,如果战斗打响,或者玩家造出第一个兵,电脑的农民开始采矿. 我们自然会 ...
- 设计模式之迭代器模式(Iterator)摘录
23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于如何创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...
- 设计模式复习-迭代器模式
Iterator.H #pragma once #include <list> #include <windows.h> using namespace std;/* 设计模式 ...
- php foreach 循环 判断index 小于多少_PHP设计模式之迭代器模式 - 硬核项目经理
一说到这个模式,就不得不提循环语句.在<大话设计模式>中,作者说道这个模式现在的学习意义更大于实际意义,这是为什么呢?当然就是被foreach这货给整得.任何语言都有这种类似的语法可以方便 ...
- Java 设计模式之迭代器模式
一.了解迭代器模式 1.1 什么是迭代器模式 迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示. 迭代器模式把游走的任务放在迭代器上,而不是聚合上.这样简化了聚合的接口和 ...
- 设计模式:迭代器模式(Iterator)
欢迎支持笔者新作:<深入理解Kafka:核心设计与实践原理>和<RabbitMQ实战指南>,同时欢迎关注笔者的微信公众号:朱小厮的博客. 欢迎跳转到本文的原文链接:https: ...
- Android设计模式之——迭代器模式
一.介绍 迭代器模式(Iterator Pattern)又称为游标(Cursor)模式,是行为型设计模式之一.迭代器模式算是一个比较古老的设计模式,其源于对容器的访问,比如Java中的List.Map ...
最新文章
- 不同浏览器的怪癖小结【转】
- ASP.NET2.0中用Gridview控件操作数据
- boost::contract模块实现customer and manager的测试程序
- VTK:图片之ImageAnisotropicDiffusion2D
- SUN JAVA面试笔试题
- 列字段通用excel导入修改版
- apue对java_[apue] 一个快速确定新系统上各类限制值的工具
- 自锁时间电路plc_1篇文章,4幅图,了解PLC接线和控制图就是这么简单
- Visual Studio2017 远程调试 Remote Debugger
- numpy flatten
- Matlab-信号处理工具箱
- 牛客网在线判题出现“请检查是否存在数组越界等非法访问情况”的情况
- docker批量导入导出镜像
- C 语言绘制指针式时钟
- 2022最新个人所得税计算(附代码)
- C语言题目代码总结解析
- java中形参和实参的区别
- 获取解析后的html内容,Android通过WebView获取解析html内容
- Android中Launcher实例
- 双重差分法(DID)入门必看
热门文章
- HomeBrew安装软件慢的简单有效解决方法
- 数据库之逻辑设计阶段(候选码、主码、外码、范式…)
- 【转载】面向对象编程的弊端是什么?
- 尝试EFM32下的fatfs的使用
- 学英语《每日一歌》之take me to your heart
- 深入浅出的解释什么是tensor
- Python爬虫入门教程 24-100 微医挂号网医生数据抓取
- 编程_从入门到遁入空门_第一篇_到底什么是编程?
- Cisco ××× Client for linux 参考手册
- 社会管理网格化 源码_威县方家营镇创新“网格化”管理模式,助推乡村社会治理能力提升...