迭代器提供了一种顺序访问集合对象中元素的方法,而无需暴漏结构的底层表示和细节。遍历集合中元素的职能从集合自己转移到迭代器对象。迭代器定义了一个用于访问集合元素并记录当前元素的接口。不一样的迭代器能够执行不一样的策略。 基础框架中的NSEnumerator类实现了迭代器模式。抽象NSEnumerator类的私有具体子类返回枚举器对象,可以顺序遍历各类集合——数组、集合、字典,把集合中的对象返回给客户端。 NSDirectoryEnumerator,这个类的实例递归枚举文件系统中一个目录的内容。NSArray、NSSet、NSDictionary这样的集合类,定义了返回与集合类型相应的NSEnumerator子类实例的方法。全部的枚举器都以一样的方式工做,能够在一个循环中向枚举器发送nextObject消息,从枚举器取得对象,直到它返回nil表示遍历结束。 html
@:遍历容器对象 @:须要访问组合对象的内容,而又不暴漏其内部表示。(案例:把封装的SDK里的对象遍历出来) @:须要经过多种方式遍历组合对象。 @:须要提供一个统一的接口,用来遍历各类类型的组合对象。
例如:数据库框架 查询数据->返回数据->封装为对象(自定义对象)->遍历(自定义迭代器变量数据库元素)java
CoCoa里的迭代器:node
NSArray *array1 = @[@"1111",@"2222",@"3333",@"4444"]; NSDictionary *dic1 = @{@"oneKey":@"oneObject",@"twoKey":@"twoObject"}; NSEnumerator *EnumerArray = [array1 objectEnumerator]; NSEnumerator *EnumberDic = [dic1 objectEnumerator]; id objct = nil; while (objct = [EnumerArray nextObject]) { NSLog(@"array遍历对象%@",objct); } id objctDic = nil; while (objctDic = [EnumberDic nextObject]) { NSLog(@"dic遍历对象%@",objctDic); } array遍历对象1111 array遍历对象2222 array遍历对象3333 array遍历对象4444 dic遍历对象oneObject dic遍历对象twoObject
建立本身的迭代器:ios
@interface Node : NSObject @property (nonatomic , copy) id data; @property (nonatomic , strong) Node *nextNode; +(Node *)addNode:(id)data; @end @implementation Node +(Node *)addNode:(id)data{ Node *node = [[self alloc]init]; node.data = data; return node; } @end #import "Node.h" @interface LinkerList : NSObject @property (nonatomic,strong) Node *headNode; -(void)addNode:(id)data; @end #import "Node.h" //链表类 @interface LinkerList : NSObject @property (nonatomic,strong) Node *headNode; -(void)addNode:(id)data; @end @implementation LinkerList -(instancetype)init{ self = [super init]; if (self){ self.headNode = [Node addNode:nil];//链表第一个为null } return self; } -(void)addNode:(id)data{ [self addData:data Node:self.headNode]; } //important 下个节点不会空,继续调用 -(void)addData:(id)data Node:(Node *)node{ if (node.nextNode == nil){ node.nextNode = [Node addNode:data]; }else{ [self addData:data Node:node.nextNode]; } } @end #import "LinkerList.h" //迭代器 @interface LinkerLterator : NSObject @property (nonatomic , strong)LinkerList *linkList; @property (nonatomic , strong)Node *currentNode; +(instancetype)LinkerLterator:(LinkerList *)list; -(Node *)nextNode; @end @implementation LinkerLterator +(instancetype)LinkerLterator:(LinkerList *)list{ LinkerLterator *lterator = [[LinkerLterator alloc]init]; lterator.linkList = list; lterator.currentNode = list.headNode; return lterator; } -(Node *)nextNode{ self.currentNode = self.currentNode.nextNode; return self.currentNode; } @end
迭代器模式-角色划分: 4个核心角色:算法
注意:之后在框架设计或者项目开发中,发现有遍历元素的场景,第一时间想到的就是迭代器模式。(OC、swift、java、C++、kotlin等)数据库
角色一:IteratorProtocol 角色二:ConcreteIterator AnyIterator->将公共功能抽象 角色三:Aggregrate(容器) 角色四:ConcreteAggregrate(容器)swift
protocol IteratorProtocol { //两个方法 //下一个元素(元素类型咱们不知道->具体类型->泛型)->ItemType //associatedtype->声明Swift泛型关键字 associatedtype ItemType func next() -> ItemType? //是否有元素 func hasNext() -> Bool } class AnyIterator<T>: IteratorProtocol { typealias ItemType = T //记录当前遍历位置 var index:Int = 0 var array:Array<T> init(array:Array<T>) { self.array = array } func next() -> T? { return nil } func hasNext() -> Bool { return false } } //什么是泛型:定义的时候不须要指定类型,使用的时候指定类型 class ConcreteIterator<T>: AnyIterator<T> { override func next() -> T? { if self.hasNext() { let result = self.array[index] index += 1 return result } return nil } override func hasNext() -> Bool { return index != self.array.count } } //容器:保存数据类型->泛型 protocol AggregrateProtocol { associatedtype DataType //添加元素 func add(data:DataType) //删除元素 func remove(index:Int) -> DataType //迭代器 //注意:协议使用不容许指定类型->必需是实现类(语法规定) func iterator() -> AnyIterator<DataType> } class ConcreteAggregrate<D>: AggregrateProtocol { //DataType给他定义一个别名 typealias DataType = D private var array = Array<D>() func add(data: D) { self.array.append(data) //系统定义容器中,也是如此设计 //array.makeIterator() } func remove(index: Int) -> D { return self.array.remove(at: index) } func iterator() -> AnyIterator<D> { //初始化(将数组传递到咱们的迭代器中,由咱们的迭代器来遍历元素) return ConcreteIterator<D>(array: self.array) } }
简化了遍历方式,对于对象集合的遍历,仍是比较麻烦的,对于数组或者有序列表,咱们尚能够经过游标来取得,但用户须要在对集合了解很清楚的前提下,自行遍历对象,可是对于hash表来讲,用户遍历起来就比较麻烦了。而引入了迭代器方法后,用户用起来就简单的多了。数组
能够提供多种遍历方式,好比说对有序列表,咱们能够根据须要提供正序遍历,倒序遍历两种迭代器,用户用起来只须要获得咱们实现好的迭代器,就能够方便的对集合进行遍历了。app
封装性良好,用户只须要获得迭代器就能够遍历,而对于遍历算法则不用去关心。框架
迭代器模式的缺点:
建立本身的迭代器参考文章:https://www.jb51.net/article/81753.htm 参考文章:https://blog.csdn.net/yuhaijian001/article/details/50394095 http://www.cocoachina.com/ios/20161028/17870.html