iOS 21种设计模式之单例(Singleton)

本文深入探讨了单例模式的概念、应用场景及其在iOS开发中的实践。介绍了单例模式如何确保类只有一个实例并提供全局访问点,特别是在Objective-C和Swift中的实现方式。此外,还讨论了单例模式可能带来的代码耦合问题及其实用性。

感谢

感谢《Pro Objective-C Design Pattern for iOS》一书,这个博客系列由很多灵感源自次书。同时,也感谢Wiki以及一些博客博主。每篇文章最后,都会列出参考链接。


这个系列的文章

  • 工厂
  • 抽象工厂
  • 单例
  • 原型
  • 生成器
  • 适配器
  • 桥接
  • 中介者
  • 观察者
  • 组合
  • 迭代器
  • 访问者
  • 装饰
  • 责任链
  • 模版
  • 策略
  • 命令
  • 享元
  • 代理
  • 备忘录
  • 总结篇:MVC
  • 进阶篇:MVVM

设计模式是为了解决一类问题而出现的,要深刻理解某个模式的应用场景,优点,缺点。千万不要为了使用而实用,那样很可能写出不伦不类的东西。

对于同一种模式,每个人的理解都不同,能解决实际问题才是关键,所以,一定要搞清楚每种设计模式究竟解决了那一类问题,对于设计模式,可以首先理解设计出的接口,再理接口内部的实现


什么是单例模式?

保证类只有一个实例,并且提供一个访问它的全局访问点

//客户端代码
let instance  = Singletonlass.sharedInstance()

 
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

在C++中,可以让构造函数为private,隐藏对应接口,但是在iOS开发中不需要,也很难做到。

在Cocoa中,单例模式的使用是十分广泛的,例如UIApplication,NSFileManager.包括一些知名的开源库,AFNetworking,SDWebImage,MagicRecord在架构的时候,也使用了单例。单例使得在使用类的时候不需要强引用一个对象。


解决什么问题?

  • 类只能有一个实例,例如一个App只能有一个UIApplication实例
  • 唯一的实例只能通过继承来扩展,并且扩展后客户端的代码不需要任何修改

什么时候使用单例?

- 类只能有一个实例,例如一个App只能有一个UIApplication实例 
- 通常单例的生命周期和App的生命周期相同,单例作为全局的访问点


不要滥用单例模式

关于单例模式的使用,objc.io的这篇文章讲的很好,摘取一些观点

  • 单例是一种全局状态,意味着App的任何地方都可以和这个单例进行交互,无形中增加了代码的耦合行
  • 单例的生命周期难以控制,虽然可以在单例中提供方法设为nil进行释放。

举个例子吧,

在我的App中,要设计一个类来统计用户的行为(这里不用友盟等第三方统计平台是因为不方便),这个类的主要任务有以下几点:

  1. 在Sandbox中建立一个Log目录,把用户行为Log到本地;
  2. 维护内存中的Log缓冲区(虽然Log相关的操作都在后台,但是还是不想频繁的于物理存储交互);
  3. 同服务器进行同步,同时根据同步的结果清理文件;
  4. 在必要的时候,能根据后台返回数据禁止Log;

那么,如何设计这个类呢?

这个类的特点:App中许多控件 or Controller都需要同它进行交互;这个类不管现在还是以后,都可以和App生命周期一致。

所以,这个类使用了单例。同时,提供类函数这样的接口(暂时没讲到接口相关的设计模式)。


Objective C中的单例

+ (instancetype)sharedSingleton {
    static Singleton *_sharedSingleton = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _sharedSingleton = [[Singleton alloc] init];
    });

    return _sharedSingleton;
}

 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

Swift的单例

注意,在Swift中由let声明的类常量支持惰性初始化(lazy),并且是线程安全的

class SingletonA {

    static let sharedInstance = SingletonA()
    //Other
}

 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

当然,也可以像Objective C中那么写

class Singleton {

    class var sharedInstance: Singleton {
        struct Static {
            static var onceToken: dispatch_once_t = 0
            static var instance: Singleton? = nil
        }
        dispatch_once(&Static.onceToken) {
            Static.instance = Singleton()
        }
        return Static.instance!
    }
}
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

参考链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值