• 128546

    文章

  • 807

    评论

  • 12

    友链

  • 最近新加了换肤功能,大家多来逛逛吧~~~~
  • 喜欢这个网站的朋友可以加一下QQ群,我们一起交流技术。

迭代器模式

服了这份高薪指南,涨多少你说了算>>

1.定义:

  迭代器提供了一种顺序访问集合对象中元素的方法,而无需暴漏结构的底层表示和细节。遍历集合中元素的职能从集合本身转移到迭代器对象。迭代器定义了一个用于访问集合元素并记录当前元素的接口。不同的迭代器可以执行不同的策略。   基础框架中的NSEnumerator类实现了迭代器模式。抽象NSEnumerator类的私有具体子类返回枚举器对象,能够顺序遍历各种集合——数组、集合、字典,把集合中的对象返回给客户端。   NSDirectoryEnumerator,这个类的实例递归枚举文件系统中一个目录的内容。NSArray、NSSet、NSDictionary这样的集合类,定义了返回与集合类型相应的NSEnumerator子类实例的方法。所有的枚举器都以同样的方式工作,可以在一个循环中向枚举器发送nextObject消息,从枚举器取得对象,直到它返回nil表示遍历结束。

2.何时使用迭代器模式?迭代器模式-场景:

@:遍历容器对象
@:需要访问组合对象的内容,而又不暴漏其内部表示。(案例:把封装的SDK里的对象遍历出来)
@:需要通过多种方式遍历组合对象。
@:需要提供一个统一的接口,用来遍历各种类型的组合对象。

例如:数据库框架 查询数据->返回数据->封装为对象(自定义对象)->遍历(自定义迭代器变量数据库元素)

CoCoa里的迭代器:

	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

创建自己的迭代器:

@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(容器)

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. 可以提供多种遍历方式,比如说对有序列表,我们可以根据需要提供正序遍历,倒序遍历两种迭代器,用户用起来只需要得到我们实现好的迭代器,就可以方便的对集合进行遍历了。

  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


695856371Web网页设计师②群 | 喜欢本站的朋友可以收藏本站,或者加入我们大家一起来交流技术!

0条评论

Loading...


发表评论

电子邮件地址不会被公开。 必填项已用*标注

自定义皮肤 主体内容背景
打开支付宝扫码付款购买视频教程
遇到问题联系客服QQ:419400980
注册梁钟霖个人博客