迭代器提供了一種順序訪問集合對象中元素的方法,而無需暴漏結構的底層表示和細節。遍歷集合中元素的職能從集合自己轉移到迭代器對象。迭代器定義了一個用於訪問集合元素並記錄當前元素的接口。不一樣的迭代器能夠執行不一樣的策略。 基礎框架中的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