迭代器模式

1.定義:

  迭代器提供了一種順序訪問集合對象中元素的方法,而無需暴漏結構的底層表示和細節。遍歷集合中元素的職能從集合自己轉移到迭代器對象。迭代器定義了一個用於訪問集合元素並記錄當前元素的接口。不一樣的迭代器能夠執行不一樣的策略。   基礎框架中的NSEnumerator類實現了迭代器模式。抽象NSEnumerator類的私有具體子類返回枚舉器對象,可以順序遍歷各類集合——數組、集合、字典,把集合中的對象返回給客戶端。   NSDirectoryEnumerator,這個類的實例遞歸枚舉文件系統中一個目錄的內容。NSArray、NSSet、NSDictionary這樣的集合類,定義了返回與集合類型相應的NSEnumerator子類實例的方法。全部的枚舉器都以一樣的方式工做,能夠在一個循環中向枚舉器發送nextObject消息,從枚舉器取得對象,直到它返回nil表示遍歷結束。 html

2.什麼時候使用迭代器模式?迭代器模式-場景:

@:遍歷容器對象
@:須要訪問組合對象的內容,而又不暴漏其內部表示。(案例:把封裝的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

3.分析:

迭代器模式-角色劃分: 4個核心角色:算法

  • 角色一:Iterator(迭代器接口)->協議 做用:定義了訪問遍歷元素的方法(標準)
  • 角色二:ConcreteIterator(具體迭代器) 做用:遍歷具體元素方法實現
  • 角色三:Aggregrate(容器接口)->協議 做用:定義了存儲元素的方法
  • 角色四:ConcreteAggregrate(具體容器) 做用:實現了存儲元素的方法

注意:之後在框架設計或者項目開發中,發現有遍歷元素的場景,第一時間想到的就是迭代器模式。(OC、swift、java、C++、kotlin等)數據庫

4.原理案例

角色一: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)
    }
    
}

5.迭代器模式的優勢有:

  1. 簡化了遍歷方式,對於對象集合的遍歷,仍是比較麻煩的,對於數組或者有序列表,咱們尚能夠經過遊標來取得,但用戶須要在對集合瞭解很清楚的前提下,自行遍歷對象,可是對於hash表來講,用戶遍歷起來就比較麻煩了。而引入了迭代器方法後,用戶用起來就簡單的多了。數組

  2. 能夠提供多種遍歷方式,好比說對有序列表,咱們能夠根據須要提供正序遍歷,倒序遍歷兩種迭代器,用戶用起來只須要獲得咱們實現好的迭代器,就能夠方便的對集合進行遍歷了。app

  3. 封裝性良好,用戶只須要獲得迭代器就能夠遍歷,而對於遍歷算法則不用去關心。框架

迭代器模式的缺點:

  1. 對於比較簡單的遍歷(像數組或者有序列表),使用迭代器方式遍歷較爲繁瑣,你們可能都有感受,像ArrayList,咱們寧肯願意使用for循環和get方法來遍歷集合。

建立本身的迭代器參考文章:https://www.jb51.net/article/81753.htm 參考文章:https://blog.csdn.net/yuhaijian001/article/details/50394095 http://www.cocoachina.com/ios/20161028/17870.html

相關文章
相關標籤/搜索