文档章节

设计模式-迭代器模式

hell03W
 hell03W
发布于 2016/11/15 16:21
字数 2014
阅读 33
收藏 0

1. 迭代器模式概述

迭代器模式, 我觉得这个图还是很贴切的. 迭代器相当于是电视机的遥控器, 聚合对象相当于是电视机. 电视机中有很多电视频道的集合, 那些电视频道到底是怎么组合在一起的, 我们并不知道, 也无需知道, 因为遥控器也就是迭代器给我们提供了遍历电视频道的方法, 我们只需要调用不同的迭代器方法即可遍历电视机中所有节目的集合.

在软件开发中, 我们经常需要使用聚合对象来存储一系列的数据. 聚合对象有两个职责: 存储数据; 遍历数据. 从依赖性来看, 前者是聚合对象的基本职责; 而后者既是可变的, 也是可分离的. 因此可将遍历数据的行为从聚合对象中分离出来, 封装在一个被称为"迭代器"的对象中, 由迭代器来提供遍历局和对象内部数据的行为, 这将简化聚合对象的设计, 更符合"单一职责原则"的要求.

迭代器模式: 提供一种方法来访问聚合对象, 而不用暴露这个对象的内部表示, 其别名为 游标. 迭代器模式是一种对象行为型模式.

在迭代器模式中包含聚合和迭代器两个层次结构, 考虑到系统的灵活性和可扩展性, 在迭代器模式中应用了工厂方法模式, 模式结构图如下:

迭代器模式中的几个角色:

  • 抽象迭代器(Iterator): 它定义了访问和遍历元素的接口, 声明了用于遍历数据元素的方法.
  • 具体迭代器(ConcreteIterator): 它实现了抽象迭代器接口, 完成对聚合对象的遍历, 同时在具体迭代器中通过游标来记录在聚合对象中所处的当前位置, 在聚合实现时, 游标通常是一个表示位置的非负整数.
  • 抽象聚合类(Aggregate): 用于存储和管理元素对象, 声明一个createIterator()方法, 该方法用于创建一个具体聚合类对象, 充当抽象迭代器的工厂角色.
  • 聚合聚合类(ConcreteAggregate): 它实现了在抽象聚合类中声明的createIterator()方法, 该方法返回一个与该具体聚合类对应的聚合迭代器ConcreateIterator实例.

在迭代器模式中,提供了一个外部的迭代器来对聚合对象进行访问和遍历,迭代器定义了一个访问该聚合元素的接口,并且可以跟踪当前遍历的元素,了解哪些元素已经遍历过而哪些没有。迭代器的引入,将使得对一个复杂聚合对象的操作变得简单。

2. Swift实现迭代器模式

一个简单的迭代器模式的Swift实现

抽象迭代器  AbsIterator 

// 抽象迭代器, 用接口来声明
protocol AbsIterator {
    
    func next()
    func isLast() -> Bool
    func previous()
    func isFirst() -> Bool
    func getNextItem() -> AnyObject
    func getPreviousItem() -> AnyObject
    
}

具体迭代器 ContreateIterator

class ContreateIterator: NSObject, AbsIterator {

    var productList: ProductList
    var list: [AnyObject]
    
    var cursor1: Int
    var cursor2: Int
    
    init(productList: ProductList) {
        
        self.productList = productList
        list = productList.objects
        cursor1 = 0
        cursor2 = list.count
        
    }
    
    func next() {
        cursor1 += 1
    }
    func isLast() -> Bool {
        return cursor1 == list.count
    }
    func previous() {
        cursor2 -= 1
    }
    func isFirst() -> Bool {
        return cursor2 == 0
    }
    func getNextItem() -> AnyObject {
        return list[cursor1]
    }
    func getPreviousItem() -> AnyObject {
        return list[cursor2]
    }
    
}

抽象聚合类 AbsObjectList

class AbsObjectList: NSObject {
    
    var objects: [AnyObject]
    
    init(objs: [AnyObject]) {
        
        objects = objs
        
    }
    
    func getObjects() -> [AnyObject] {
        return objects;
    }
    
    func addObject(obj: AnyObject) {
        objects.append(obj)
    }
    
    func removeObject(obj: AnyObject) {
        
    }
    
    func createIterator() -> AbsIterator {
        return Optional.none!
    }
}

具体聚合类 ProductList

class ProductList: AbsObjectList {
    
    override init(objs: [AnyObject]) {
        super.init(objs: objs)
    }
    
    override func createIterator() -> AbsIterator {
        return ContreateIterator(productList: self)
    }
}





客户端代码:

var array = [String]()

array.append("walden")
array.append("wei")
array.append("shengli")
array.append("liuyong")
array.append("jinlong")

let products = ProductList(objs: array as [AnyObject])

let iterator = products.createIterator()

print("\(iterator.getNextItem())")

如果在如上所示代码中增加新的具体聚合类, 只需增加新的聚合类子类和一个新的具体迭代器类, 原有类库代码无需修改, 符合开闭原则; 如果需要更换迭代器, 只需要增加一个新的具体迭代器作为抽象迭代器的子类, 重新实现遍历方法, 符合开闭原则; 但是如果要在迭代器中增加新的方法, 则需要修改抽象迭代器源代码, 这将违背开闭原则.

在迭代器模式的结构图中, 我们可以看到具体迭代器类和具体聚合类之间存在双重关系, 其中一个关系为关联关系, 在具体迭代器中需要维持一个队具体聚合对象的引用, 该关联关系的目的是访问存储在聚合对象中的数据, 以便迭代器能够对这些数据进行遍历操作. 除了使用关联关系, 为了能够让迭代器可以访问到聚合对象中的数据, 我们可以将迭代器设计为聚合类的内部类, 在java的JDK中, 就是通过这种方式实现的.

3. 总结

迭代器模式是一种使用频率非常高的设计模式,通过引入迭代器可以将数据的遍历功能从聚合对象中分离出来,聚合对象只负责存储数据,而遍历数据由迭代器来完成。由于很多编程语言的类库都已经实现了迭代器模式,因此在实际开发中,我们只需要直接使用Java、C#等语言已定义好的迭代器即可,迭代器已经成为我们操作聚合对象的基本工具之一。

3.1 主要优点

迭代器模式的主要优点如下:

  1. 它支持以不同的方式遍历一个聚合对象,在同一个聚合对象上可以定义多种遍历方式。在迭代器模式中只需要用一个不同的迭代器来替换原有迭代器即可改变遍历算法,我们也可以自己定义迭代器的子类以支持新的遍历方式。
  2. 迭代器简化了聚合类。由于引入了迭代器,在原有的聚合对象中不需要再自行提供数据遍历等方法,这样可以简化聚合类的设计。
  3. 在迭代器模式中,由于引入了抽象层,增加新的聚合类和迭代器类都很方便,无须修改原有代码,满足“开闭原则”的要求。

2. 主要缺点

迭代器模式的主要缺点如下:

  1. 由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。
  2. 抽象迭代器的设计难度较大,需要充分考虑到系统将来的扩展,例如JDK内置迭代器Iterator就无法实现逆向遍历,如果需要实现逆向遍历,只能通过其子类ListIterator等来实现,而ListIterator迭代器无法用于操作Set类型的聚合对象。在自定义迭代器时,创建一个考虑全面的抽象迭代器并不是件很容易的事情。

3. 适用场景

在以下情况下可以考虑使用迭代器模式:

  1. 访问一个聚合对象的内容而无须暴露它的内部表示。将聚合对象的访问与内部数据的存储分离,使得访问聚合对象时无须了解其内部实现细节。
  2. 需要为一个聚合对象提供多种遍历方式。
  3. 为遍历不同的聚合结构提供一个统一的接口,在该接口的实现类中为不同的聚合结构提供不同的遍历方式,而客户端可以一致性地操作该接口。

更多详情请参考原文:

Reference: http://blog.csdn.net/lovelion/article/details/9992005

本文转载自:http://blog.csdn.net/lovelion/article/details/9992005

hell03W
粉丝 9
博文 145
码字总数 109892
作品 0
朝阳
程序员
私信 提问
JavaScript设计模式总结

之前看过《JavaScript设计模式与开发实践》这本书,对书中的设计模式和一些相关案例也有了一定的了解,同时把这些设计模式的应用对应在在一些其他的项目中,进行了一些整理,如下仅供参考: ...

jefferyE
03/26
0
0
设计模式 2014-12-19

book: 阎宏《JAVA与模式》 架构设计栏目 http://blog.csdn.net/enterprise/column.html 概要: http://bbs.csdn.net/forums/Embeddeddriver 23种设计模式分别是: 1.单例模式 2.工厂方法模式...

jayronwang
2014/12/19
0
0
JavaScript 常见设计模式

前言 设计模式,这一话题一直都是程序员谈论的"高端"话题之一。许多程序员从设计模式中学到了设计软件的灵感和解决方案。 有人认为设计模式只在 C++或者 Java 中有用武之地,JavaScript 这种...

YeeWang王大白
03/08
0
0
JavaScript 中常见设计模式整理

开发中,我们或多或少地接触了设计模式,但是很多时候不知道自己使用了哪种设计模式或者说该使用何种设计模式。本文意在梳理常见设计模式的特点,从而对它们有比较清晰的认知。 JavaScript 中...

牧云云
2018/05/18
0
0
【设计模式笔记】(十六)- 代理模式

一、简述 代理模式(Proxy Pattern),为其他对象提供一个代理,并由代理对象控制原有对象的引用;也称为委托模式。 其实代理模式无论是在日常开发还是设计模式中,基本随处可见,中介者模式中...

MrTrying
2018/06/24
0
0

没有更多内容

加载失败,请刷新页面

加载更多

我的程序人生——三年开发的思考,阿里朋友给我总结的“Java架构师技术栈”

想写这篇文章已经很久了,本来计划在3月份,也就是刚好满3年的时候写的,但是因为各种各样的原因推到了现在才开始码字。 小感慨 三年是一段很长的时间,它足够让你从高中毕业进入大学,也能让...

我最喜欢三大框架
12分钟前
0
0
ElasticSearch获取索引信息

检查集群的健康情况 GET /_cat/health?v green:每个索引的primary shard和replica shard都是active状态的 yellow:每个索引的primary shard都是active状态的,但是部分replica shard不是act...

水木星辰
14分钟前
0
0
Cesium中级教程6 - 3D Models 三维模型

Cesium中文网:http://cesiumcn.org/ | 国内快速访问:http://cesium.coinidea.com/ 3D Models 三维模型 本教程将教您如何通过Primitive API转换、加载和使用Cesium中的三维模型。如果你是C...

Cesium中文网
16分钟前
0
0
Elasticsearch简单学习1-用白话文解释原理

由于Elasticsearch在工作中用的越来越多,平时是边学边用,很少记录,读到一些很好的文章时间久了就忘记了。 所以,在此记录一下,希望对更多人的学习有帮助,知识在于分享! ==============...

wind2012
24分钟前
0
0
Spring面试题部分总结【慨念】

什么是Spring? spring是一个企业级应用的开源开发框架,主要用来开发java应用,spring框架目标就是简化企业级应用开发。 Spring用到了那些设计模式? spring里面用到了大量的设计模式,这里...

薛小二
25分钟前
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部