23种设计模式(八)

版本记录

版本号 时间
V1.0 2017.04.28

前言

前面讲了23种设计模式中的前几个,下面我们继续,先看前几篇文章。
1. 23种设计模式(一)
2. 23种设计模式(二)
3. 23种设计模式(三)
4. 23种设计模式(四)
5. 23种设计模式(五)
6. 23种设计模式(六)
7. 23种设计模式(七)

详述

十五、迭代器模式——Iterator

  提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示。OC中迭代器已经实现的很完美了。我简单的举几个例子。

1. 迭代器

    NSArray *arr = [NSArray arrayWithObjects:@"bei", @"jing", @"huan", @"ying", @"nin", nil];
    NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:@"value1", @"key1", @"value2", @"key2", nil];
        
    // 创建数组 正序 迭代器
    NSEnumerator *arrEnumer1 = [arr objectEnumerator];
        
    // 创建数组 反序 迭代器
    NSEnumerator *arrEnumer2 = [arr reverseObjectEnumerator];
        
    // 创建字典 key 迭代器
    NSEnumerator *dicKeyEnumer = [dic keyEnumerator];
        
    // 创建字典 对象 迭代器
    NSEnumerator *dicObjEnumer = [dic objectEnumerator];
        
    // 获取迭代器中下一个对象
    id obj = [arrEnumer1 nextObject];
        
    // 获取迭代器中所有对象
    NSArray *array = [arrEnumer2 allObjects];




2. 数组用迭代器遍历
    NSArray *array = [NSArray arrayWithObjects:@"bei", @"jing", @"huan", @"ying", @"nin", nil];
        
    // 获取数组的正序迭代器
    NSEnumerator *enu1 = [array objectEnumerator];
        
    // 获取数组的反序迭代器
    NSEnumerator *enu2 = [array reverseObjectEnumerator];
        
    // 遍历数组
    id obj = nil;
        
    // 正序,获取下一个需要遍历的元素
    while (obj = [enu1 nextObject]) {
        NSLog(@"%@", obj);
    }
        
    // 反序,获取下一个需要遍历的元素
    while (obj = [enu2 nextObject]) {
        NSLog(@"%@", obj);
    }


3. 集合用迭代器
    NSSet *set = [NSSet setWithObjects:@5, @23, @3, @8, @21, @33, @18, nil];
        
    NSEnumerator *enu = [set objectEnumerator];
        
    id obj = nil;
        
    while (obj = [enu nextObject]) {
        NSLog(@"%@", obj);
    }



4. 字典用迭代器

    NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:@"value1", @"key1", @"value2", @"key2", nil];
        
    // key 迭代器
    NSEnumerator *keyEnumer = [dic keyEnumerator];
        
    id key = nil;
    while (key = [keyEnumer nextObject]) {
        NSLog(@"%@ = %@", key, [dic objectForKey:key]);
    }
        
    // 对象迭代器
    NSEnumerator *objEnumer = [dic objectEnumerator];
        
    id obj = nil;
    while (obj = [objEnumer nextObject]) {
        NSLog(@"%@", obj);
    }


结论:直接看代码体会,都能看懂。


十六、单例模式——Singleton

  保证一个类仅有一个实例,使它们都可以独立地变化。

我先说一下我们自定义的单例,先看代码。


1. HCDSingleton.h

#import <Foundation/Foundation.h>

@interface HCDSingleton : NSObject

+ (instancetype)sharedInstance;

@end

2. HCDSingleton.m
#import "HCDSingleton.h"

@implementation HCDSingleton

+ (instancetype)sharedInstance

{
    static HCDSingleton *singleton = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        singleton = [[HCDSingleton alloc]init];
    });
    return singleton;
}

@end


  上面的是我们自定义的单例。 就我本身理解而言,我认为的单例在整个工程中,就相当于一个全局变量,不论在哪里需要用到这个类的实例变量,都可以通过单例方法来取得,而且一旦你创建了一个单例类,不论你在多少个界面中初始化调用了这个单例方法取得对象,它们所有的对象都是指向的同一块内存存储空间(即单例类保证了该类的实力对象是唯一存在的一个)。“单例模式”是我们在iOS中最常使用的设计模式之一。单例模式不需要传递任何参数,就有效地解决了不同代码间的数据共享问题。

  ios中还有很多系统的单例,比如NSUserDefaults就是单例,UIApplication类有一个方法叫sharedApplication也是一个单例,NSNotificationCenter(消息中心) 、NSFileManager(文件管理) 、NSURLCache(请求缓存)、NSHTTPCookieStorage(应用程序cookies池)都是系统单例。

下面我们就说一下单例的实现方式。

1.通过线程加锁实现

 +(DBManager *)sharedManager;    (.h文件中)
 
 // m文件中的实现:
 + (DBManager *)sharedManager{
  Static DBManager *manager = nil;
  @synchronized(self){
  if(manager == nil){
    manager = [[DBManager alloc]init];
     }
   }
  return manager;
}

2. 通过GCD实现单例方法:

+(DBManager *)sharedManager;    (.h文件中)
 
 //.m文件中的实现:
 + (DBManager *)sharedManager{
  Static DBManager *manager = nil;
      static dispatch_once_t token;
      dispatch_once(&token,^{
              if(manager == nil){
           manager = [[DBManager alloc]init];
        }
   } );
  return manager;
}


3.  重写allocWithZone方法,用来保证其他人直接使用alloc和init试图获得一个新实例的时候不产生一个新实例,
+ (id)allocWithZone:(NSZone *)zone{
    @synchronized(self){
        if (!manager) {
            manager = [super allocWithZone:zone]; //确保使用同一块内存地址
            return manager;
        }
        return nil;
    }
}

4. 适当实现copyWithZone,release和autorelease。


-  (id)init;
{
    @synchronized(self) {
        if (self = [super init]){
            return self;
        }
        return nil;
    }
}


下面就集中说一下ARC和非ARC下的单例模式设计。

1. ARC中单例设计模式

//.h文件
#import <Foundation/Foundation.h>

@interface Singleton : NSObject

//单例方法
+(instancetype)sharedSingleton;

@end

//.m文件
#import "Singleton.h"

@implementation Singleton

//全局变量
static id _instance = nil;

//单例方法
+  (instancetype)sharedSingleton
{
    return [[self alloc] init];
}

//alloc会调用allocWithZone:
+  (instancetype)allocWithZone:(struct _NSZone *)zone
{
    //只进行一次
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [super allocWithZone:zone];
    });
    return _instance;
}

//初始化方法
-  (instancetype)init
{
    // 只进行一次
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [super init];
    });
    return _instance;
}

//copy在底层 会调用copyWithZone:

-  (id)copyWithZone:(NSZone *)zone
{
    return  _instance;
}
+  (id)copyWithZone:(struct _NSZone *)zone
{
    return  _instance;
}
+  (id)mutableCopyWithZone:(struct _NSZone *)zone
{
    return _instance;
}
-  (id)mutableCopyWithZone:(NSZone *)zone
{
    return _instance;
}

@end




2. 非ARC下的单例模式设计
//.m文件

#import <Foundation/Foundation.h>

//单例方法
@interface Singleton : NSObject

+ (instancetype)sharedSingleton;

@end

//.m文件

#import "Singleton.h"

@implementation Singleton
//全局变量
static id _instance = nil;

//单例方法
+(instancetype)sharedSingleton
{
    //系统的大多数类方法都有做autorelease,所以我们也需要做一下
     return [[[self alloc] init] autorelease];
}

//alloc会调用allocWithZone:
+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
    //只进行一次
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [super allocWithZone:zone];
    });
    return _instance;
}

//初始化方法
- (instancetype)init
{
    // 只进行一次
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [super init];
    });
    return _instance;
}

- (oneway void)release
{
    //什么都不做 保证单例对象不被销毁
}

//返回本身 保证只有一个单例对象
- (instancetype)retain
{
    return _instance;
} 

//计数器为1 保证只有一个单例对象
-  (NSUInteger)retainCount
{
    return 1;
}

//copy在底层 会调用copyWithZone:
+ (id)copyWithZone:(struct _NSZone *)zone
{
    return  _instance;
}
- (id)copyWithZone:(NSZone *)zone
{
    return _instance;
}
+ (id)mutableCopyWithZone:(struct _NSZone *)zone
{
    return _instance;
}
- (id)mutableCopyWithZone:(NSZone *)zone
{
    return _instance;
}
@end



后记

未完,待续,休息了,谢谢大家。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容