迭代器模式

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

相关文章
相关标签/搜索