迭代器模式实验含答案.docx
《迭代器模式实验含答案.docx》由会员分享,可在线阅读,更多相关《迭代器模式实验含答案.docx(14页珍藏版)》请在冰豆网上搜索。
迭代器模式实验含答案
课程名称:
软件体系结构与设计
迭代器(Iterator)模式实验
一、实验目的
1.掌握迭代器模式的概念;
2.掌握迭代器模式的功能;
3.加深对迭代器模式的了解;
4.提高对迭代器模式的运用;
5.将该模式运用但实际的生活中。
二、实验内容
1.阅读和查看资料了解迭代器模式的概念和功能;
2.将有关代理模式的迭代器模式理解透彻并运行;
3.举例说明生活中的一个可以使用迭代器模式的例子;
4.熟悉迭代器模式的扩展,迭代器模式是比较有用途的一种模式,而且变种较多,应用场合覆盖从小结构到整个系统的大结构。
三、实验环境
Windows7、Java虚拟机、MyEclipse环境下运行代码。
4、实验设计原理
迭代器(Iterator)模式,又叫做游标(Cursor)模式。
它提供一种方法顺序访问一个聚合对象(或容器对象:
container)中各个元素,而又不需暴露该对象的内部。
聚合:
表示一组对象的组合结构,比如JAVA中的数组,集合等从定义可见,迭代器模式是为容器而生。
很明显,对容器对象的访问必然涉及到遍历算法。
你可以一股脑的将遍历方法塞到容器对象中去;或者根本不去提供什么遍历算法,让使用容器的人自己去实现去吧。
这两种情况好像都能够解决问题。
然而在前一种情况,容器承受了过多的功能,它不仅要负责自己“容器”内的元素维护(添加、删除等等),而且还要提供遍历自身的接口;而且由于遍历状态保存的问题,不能对同一个容器对象同时进行多个遍历。
第二种方式倒是省事,却又将容器的内部细节暴露无遗。
而迭代器模式的出现,很好的解决了上面两种情况的弊端。
迭代器模式的类图如下图所示:
类图解读:
从结构上可以看出,迭代器模式在客户与容器之间加入了迭代器角色。
迭代器角色的加入,就可以很好的避免容器内部细节的暴露,而且也使得设计符号“单一职责原则”。
注意,在迭代器模式中,具体迭代器角色和具体容器角色是耦合在一起的——遍历算法是与容器的内部细节紧密相关的。
为了使客户程序从与具体迭代器角色耦合的困境中脱离出来,避免具体迭代器角色的更换给客户程序带来的修改,迭代器模式抽象了具体迭代器角色,使得客户程序更具一般性和重用性。
这被称为多态迭代。
迭代器模式所涉及的角色有:
参与者:
•迭代器角色(Iterator):
定义访问和遍历元素的接口。
•具体迭代器角色(ConcreteIterator):
关联到被迭代的具体聚集对象角色,继承迭代器角色实现具体的迭代,并负责管理记录遍历中的当前位置。
•聚集对象抽象角色(Aggregate):
负责提供创建具体迭代器角色的接口。
•具体聚集对象角色(ConcreteAggreate):
持有一个对象的集合,实现创建具体迭代器角色的接口,返回集合遍历所依赖的一个迭代器。
●一个迭代器模式例子:
●20世纪80年代的黑白电视机,没有遥控器,每次开关机或者换台都需要通过电视机上面的那些按钮来完成,如果你想换台的话,需要亲自用手去旋转换台的按钮,每转一下就“啪”的响一声,如果没有收到任何电视频道就会出现一片让人眼花的雪花点。
还要移动电视机上面那两根可以前后左右移动变长变短的天线。
随着科技的飞速发展,越来越高级的电视机相继出现,那种古老的电视机几乎看不到了。
与那时的电视机相比,现今的电视机给我们带来的最大便利之一就是增加了电视机遥控器,我们在进行开机、关机、换台、改变音量等操作时都无须直接操作电视机,可以通过遥控器来间接实现。
我们可以将电视机看成一个存储电视频道的集合对象,通过遥控器可以对电视机中的电视频道集合进行操作,如返回上一个频道、跳转到下一个频道或者跳转至指定的频道。
遥控器为我们操作电视频道带来很大的方便,用户并不需要知道这些频道到底如何存储在电视机中。
电视机遥控器和电视机示意图如图1所示:
●
●在软件开发中,也存在大量类似电视机一样的类,它们可以存储多个成员对象(元素),这些类通常称为聚合类(AggregateClasses),对应的对象称为聚合对象。
为了更加方便地操作这些聚合对象,同时可以很灵活地为聚合对象增加不同的遍历方法,我们也需要类似电视机遥控器一样的角色,可以访问一个聚合对象中的元素但又不需要暴露它的内部结构。
本章我们将要学习的迭代器模式将为聚合对象提供一个遥控器,通过引入迭代器,客户端无须了解聚合对象的内部结构即可实现对聚合对象中成员的遍历,还可以根据需要很方便地增加新的遍历方式。
●迭代器模式的作用:
●迭代器模式能够遍历一组聚合对象,不需要了解其内部结构还能提供不同的遍历方法。
●就是分离了集合对象的遍历行为,将遍历算法交给这个迭代器角色来完成,可以很好的避免容器内部细节的暴露,而且也使得设计符合“单一职责原则”,另外迭代器模式抽象了具体迭代器角色,可以通过对一个抽象迭代器多个集成可来完成同一聚集对象的多种遍历。
五、迭代器模式示例性代码
首先有一个抽象的聚集,所谓的聚集就是就是数据的集合,可以循环去访问它。
它只有一个方法GetIterator()让子类去实现,用来获得一个迭代器对象。
1 ///
2
3 /// 抽象聚集
4
5 ///
6
7 public interface IList
8
9 {
10 IIterator GetIterator();
11 }
抽象的迭代器,它是用来访问聚集的类,封装了一些方法,用来把聚集中的数据按顺序读取出来。
通常会有MoveNext()、CurrentItem()、Fisrt()、Next()等几个方法让子类去实现。
1 ///
2
3 /// 抽象迭代器
4
5 ///
6
7 public interface IIterator
8 {
9 bool MoveNext();
10
11 Object CurrentItem();
12
13 void First();
14
15 void Next();
16 }
具体的聚集,它实现了抽象聚集中的唯一的方法,同时在里面保存了一组数据,这里我们加上Length属性和GetElement()方法是为了便于访问聚集中的数据。
1 ///
2
3 /// 具体聚集
4
5 ///
6
7 public class ConcreteList :
IList
8 {
9 int[] list;
10
11 public ConcreteList()
12
13 {
14 list = new int[] { 1,2,3,4,5};
15 }
16
17 public IIterator GetIterator()
18
19 {
20 return new ConcreteIterator(this);
21 }
22
23 public int Length
24
25 {
26 get { return list.Length; }
27 }
28
29 public int GetElement(int index)
30
31 {
32 return list[index];
33 }
34 }
具体迭代器,实现了抽象迭代器中的四个方法,在它的构造函数中需要接受一个具体聚集类型的参数,在这里面我们可以根据实际的情况去编写不同的迭代方式。
1 /**////
2
3 /// 具体迭代器
4
5 ///
6
7 public class ConcreteIterator :
IIterator
8
9 {
10 private ConcreteList list;
11
12 private int index;
13
14 public ConcreteIterator(ConcreteList list)
15
16 {
17 this.list = list;
18
19 index = 0;
20 }
21
22 public bool MoveNext()
23
24 {
25 if (index < list.Length)
26
27 return true;
28
29 else
30
31 return false;
32 }
33
34 public Object CurrentItem()
35
36 {
37 return list.GetElement(index) ;
38 }
39
40 public void First()
41
42 {
43 index = 0;
44 }
45
46 public void Next()
47
48 {
49 if (index < list.Length)
50
51 {
52 index++;
53 }
54 }
55 }
简单的客户端程序调用:
1 /**////
2
3 /// 客户端程序
4
5 ///
6
7 class Program
8
9 {
10 static void Main(string[] args)
11
12 {
13 IIterator iterator;
14
15 IList list = new ConcreteList();
16
17 iterator = list.GetIterator();
18
19 while (iterator.MoveNext())
20
21 {
22 int i = (int)iterator.CurrentItem();
23 Console.WriteLine(i.ToString());
24
25 iterator.Next();
26 }
27
28 Console.Read();
29
30 }
31
32 }
Iterator实现要点:
1.迭代抽象:
访问一个聚合对象的内容而无需暴露它的内部表示。
2.迭代多态:
为遍历不同的集合结构提供一个统一的接口,从而支持同样的算法在不同的集合结构上进行操作。
3.迭代器的健壮性考虑:
遍历的同时更改迭代器所在的集合结构,会导致问题。
题目:
假设某软件公司Z为某超市开发了一套销售管理系统,在对该系统进行分析和设计时,Z公司开发人员发现经常需要对系统中的商品数据、客户数据等进行遍历,为了复用这些遍历代码,Z公司开发人员设计了一个抽象的数据聚合类AbstractObjectList,而将存储商品和客户登记的类作为其子类。
AbstractObjectList类结构如下图所示。
在上图中,IList类型的对象objects用于存储数据,AbstractObjectList类的方法说明如下表所示:
AbstractObjectList类的子类ProductList和CustomerList分别用于存储商品数据和客户数据。
请用迭代器模式编程实现。
代码:
importjava.util.*;
//抽象聚合类
abstractclassAbstractObjectList{
protectedList
publicAbstractObjectList(Listobjects){
this.objects=objects;
}
publicvoidaddObject(Objectobj){
this.objects.add(obj);
}
publicvoidremoveObject(Objectobj){
this.objects.remove(obj);
}
publicListgetObjects(){
returnthis.objects;
}
//声明创建迭代器对象的抽象工厂方法
publicabstractAbstractIteratorcreateIterator();
}
//商品数据类:
具体聚合类
classProductListextendsAbstractObjectList{
publicProductList(Listproducts){
super(products);
}
//实现创建迭代器对象的具体工厂方法
publicAbstractIteratorcreateIterator(){
returnnewProductIterator(this);
}
}
//客户数据类:
具体聚合类
classCustomerListextendsAbstractObjectList{
publicCustomerList(Listcustomers){
super(customers);
}
//实现创建迭代器对象的具体工厂方法
publicAbstractIteratorcreateIterator(){
returnnewCustomerIterator(this);
}
}
//抽象迭代器
interfaceAbstractIterator{
publicvoidnext();//移至下一个元素
publicbooleanisLast();//判断是否为最后一个元素
publicvoidprevious();//移至上一个元素
publicbooleanisFirst();//判断是否为第一个元素
publicObjectgetNextItem();//获取下一个元素
publicObjectgetPreviousItem();//获取上一个元素
}
//商品迭代器:
具体迭代器
classProductIteratorimplementsAbstractIterator{
privateProductListproductList;
privateListproducts;
privateintcursor1;//定义一个游标,用于记录正向遍历的位置
privateintcursor2;//定义一个游标,用于记录逆向遍历的位置
publicProductIterator(ProductListlist){
this.productList=list;
this.products=list.getObjects();//获取集合对象
cursor1=0;//设置正向遍历游标的初始值
cursor2=products.size()-1;//设置逆向遍历游标的初始值
}
publicvoidnext(){
if(cursor1cursor1++;
}
}
publicbooleanisLast(){
return(cursor1==products.size());
}
publicvoidprevious(){
if(cursor2>-1){
cursor2--;
}
}
publicbooleanisFirst(){
return(cursor2==-1);
}
publicObjectgetNextItem(){
returnproducts.get(cursor1);
}
publicObjectgetPreviousItem(){
returnproducts.get(cursor2);
}
}
//客户迭代器:
具体迭代器
classCustomerIteratorimplementsAbstractIterator{
privateCustomerListcustomerList;
privateListcustomers;
privateintcursor1;//定义一个游标,用于记录正向遍历的位置
privateintcursor2;//定义一个游标,用于记录逆向遍历的位置
publicCustomerIterator(CustomerListlist){
this.customerList=list;
this.customers=list.getObjects();//获取集合对象
cursor1=0;//设置正向遍历游标的初始值
cursor2=customers.size()-1;//设置逆向遍历游标的初始值
}
publicvoidnext(){
if(cursor1cursor1++;
}
}
publicbooleanisLast(){
return(cursor1==customers.size());
}
publicvoidprevious(){
if(cursor2>-1){
cursor2--;
}
}
publicbooleanisFirst(){
return(cursor2==-1);
}
publicObjectgetNextItem(){
returncustomers.get(cursor1);
}
publicObjectgetPreviousItem(){
returncustomers.get(cursor2);
}
}
publicclassIterator{
publicstaticvoidmain(Stringargs[]){
Listproducts=newArrayList();
products.add("农夫山泉");
products.add("百岁山");
products.add("康师傅");
products.add("旺仔");
products.add("统一");
AbstractObjectListlist;
AbstractIteratoriterator;
list=newProductList(products);//创建聚合对象
iterator=list.createIterator();//创建迭代器对象
System.out.println("***************商品数据***************");
System.out.println("正向遍历:
");
while(!
iterator.isLast()){
System.out.print(iterator.getNextItem()+",");
iterator.next();
}
System.out.println();
System.out.println("逆向遍历:
");
while(!
iterator.isFirst()){
System.out.print(iterator.getPreviousItem()+",");
iterator.previous();
}
Listcustomers=newArrayList();
customers.add("张三");
customers.add("李四");
customers.add("王五");
customers.add("赵六");
AbstractObjectListlist1;
AbstractIteratoriterator1;
list1=newProductList(customers);//创建聚合对象
iterator1=list1.createIterator();//创建迭代器对象
System.out.println();
System.out.println("***************客户数据***************");
System.out.println("正向遍历:
");
while(!
iterator1.isLast()){
System.out.print(iterator1.getNextItem()+",");
iterator1.next();
}
System.out.println();
System.out.println("逆向遍历:
");
while(!
iterator1.isFirst()){
System.out.print(iterator1.getPreviousItem()+",");
iterator1.previous();
}
}
}