zoukankan      html  css  js  c++  java
  • iOS设计模式之迭代器模式

    迭代器模式

    基本理解

    • 迭代器模式(Iterrator):提供一个方法顺序访问一个聚合对象中的各个元素,而又不暴露该元素的内部表示。
    • 当你访问一个聚合对象,而且不管这些对象是什么都需要遍历的时候,你就应该考虑用迭代器模式。
    • 你需要对聚集有多种方式遍历时,可以考虑用迭代器模式。
    • 迭代器模式就是分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可让外部代码透明地访问集合内部的数据。
    • 迭代器定义了一个用于访问集合元素并记录当前元素的接口。
    • 不同的迭代器可以执行不同的迭代策略。
    • 外部迭代器和内部迭代器
      • 外部迭代器
      • 外部迭代器让客户端直接操作迭代过程,所以客户端需要知道外部迭代器才能使用。但是它为客户端提供了更多的控制
      • 客户端创建并维护外部迭代器
      • 客户端可以使用不同外部迭代器实现多种类型的遍历
      • 内部迭代器
        • 客户端不需要知道任何外部迭代器,而是可以通过集合对象的特殊接口,或者一次访问一个元素,或者向集合中的每个元素发送消息。
        • 集合对象本身创建并维护它的外部迭代器
        • 集合对象可以在不修改客户端代码的情况下,选择不同的外部迭代器

    何时使用迭代器

    • 需要访问组合对象的内容,而又不是暴露其内部标示
    • 需要通过多种方式遍历组合对象
    • 需要提供一个统一的接口,用来遍历各种类型的组合对象

    在Cocoa Touch框架中使用迭代器模式

    • 苹果公司用自己命名规则“枚举器/枚举”改写了迭代器模式,用于相关基础类的各种方法。也就是说枚举就是苹果版本的迭代。

    • 基础框架中的NSEnumerator类实现了迭代器模式。抽象NSEnumerator类的私有具体子类返回枚举器对象,能够顺序遍历各种几何--数组、集(set)、字典(值与键),把集合的对象返回给客户端。

    • NSEnumerator可以枚举NSArray/NSDictionary和NSSet对象中的元素。它本身是个抽象类。它依靠几个工厂方法,如objectEnumerator或keyEnumerator,来创建并返回相应的具体枚举器对象。

    • 从iOS4开始,有了另一种枚举Cocoa Touch框架中集合对象的方法,叫做基于块的枚举。

    • 快速枚举,这个是苹果推荐的枚举方法。它允许把集合对象的枚举直接用作for循环的一部分,无需使用其他枚举器对象,而且比传统的基于索引的for循环效率更高,形如:

       NSArray *arr = @[@"zhangsan",@"lisi",@"wangwu"];
       
       for(NSString *item in arr)
       {
           NSLog(@"%@",item);
       }
      

    例子

    该例子定义了一个集合Set和一个迭代器ConcreteIterator。然后通过迭代器来输出集合Set对象的元素。
    ConcreteSet.h

    //
    //  ConcreteSet.h
    //  IterationDemo
    //
    //  Created by zhanggui on 15/8/8.
    //  Copyright (c) 2015年 zhanggui. All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    
    @interface ConcreteSet : NSObject
    {
        NSMutableArray *items;
    }
    -(NSInteger)getCount;
    -(id)getItemFromIndex:(NSInteger)index;
    
    -(void)insertItem:(id)item;
    
    @end
    

    ConcreteSet.m

         	//
    //  ConcreteSet.m
    //  IterationDemo
    //
    //  Created by zhanggui on 15/8/8.
    //  Copyright (c) 2015年 zhanggui. All rights reserved.
    //
    
    #import "ConcreteSet.h"
    #import "ConcreteIterator.h"
    @implementation ConcreteSet
    
    -(id)init
    {
        self = [super init];
        if (self) {
            items = [NSMutableArray new];
        }
        return self;
    }
    -(NSInteger)getCount
    {
        return [items count];
    }
    -(id)getItemFromIndex:(NSInteger)index
    {
        return [items objectAtIndex:index];
    }
    -(ConcreteIterator *)createiterator
    {
        return [ConcreteIterator new];
    }
    -(void)insertItem:(id)item
    {
        [items addObject:item];
    }
    @end
    

    Concreteiterator.h

          	//
    //  ConcreteIterator.h
    //  IterationDemo
    //
    //  Created by zhanggui on 15/8/8.
    //  Copyright (c) 2015年 zhanggui. All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    
    @class ConcreteSet;
    @interface ConcreteIterator : NSObject
    {
        ConcreteSet *mySet;
        int current;
    }
    
    -(id)FirstItem;
    
    -(id)nextItem;
    
    
    -(BOOL)isFinish;
    
    -(id)currentItem;
    -(id)initWithConcreteSet:(ConcreteSet *)concrete;
    @end
    

    Concreteiterator.m

    //
    //  ConcreteIterator.m
    //  IterationDemo
    //
    //  Created by zhanggui on 15/8/8.
    //  Copyright (c) 2015年 zhanggui. All rights reserved.
    //
    
    #import "ConcreteIterator.h"
    #import "ConcreteSet.h"
    
    @implementation ConcreteIterator
    
    -(id)initWithConcreteSet:(ConcreteSet *)concrete
    {
        self = [super init];
        if (self) {
            mySet = concrete;
        }
        
        return self;
    }
    
    -(id)FirstItem
    {
        return [mySet getItemFromIndex:0];
    }
    -(id)nextItem
    {
        current ++;
        if (current<[mySet getCount]) {
            return [mySet getItemFromIndex:current];
        }else
        {
            return nil;
        }
    }
    -(BOOL)isFinish
    {
        return current>=[mySet getCount] ? YES : NO;
    }
    -(id)currentItem
    {
        return [mySet getItemFromIndex:current];
    }
    @end
    

    然后在ViewController中测试

    //
    //  ViewController.m
    //  IterationDemo
    //
    //  Created by zhanggui on 15/8/8.
    //  Copyright (c) 2015年 zhanggui. All rights reserved.
    //
    
    #import "ViewController.h"
    #import "ConcreteIterator.h"
    #import "ConcreteSet.h"
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    //    NSArray *arr = @[@"apple",@"banana",@"orange"];
    //    
    //    for(NSString *item in arr)
    //    {
    //        NSLog(@"%@",item);
    //    }
        ConcreteSet *set = [[ConcreteSet alloc] init];
        [set insertItem:@"apple"];
        [set insertItem:@"banana"];
        [set insertItem:@"orange"];
        
        NSLog(@"Count is :%ld",(long)[set getCount]);
        
        ConcreteIterator *iterator = [[ConcreteIterator alloc] initWithConcreteSet:set];
        
        while (![iterator isFinish]) {
            NSLog(@"%@",[iterator currentItem]);
            [iterator nextItem];
        }
    }
    
    
    @end
    

    用自己定义的迭代器去输出元素和用苹果枚举效果类似。苹果推荐使用类似与viewDidLoad方法中的for循环来输出集合元素。

    附:

  • 相关阅读:
    进制转换
    体验mssql-cli
    从Windows迁移SQL Server到Linux
    CentOS7脱机安装SQL Server 2017
    基础知识:数据类型优先级
    SQL Server 2016正式版安装(超多图)
    制造高CPU使用率的简单方法
    SQL Server启动的几种方法
    SQL Server 2016 RC0 安装(超多图)
    机器学习:Python实现单层Rosenblatt感知器
  • 原文地址:https://www.cnblogs.com/zhanggui/p/4712795.html
Copyright © 2011-2022 走看看