单例模式
基础理解
- 所有类都有构造方法,不编码则系统默认生成空的构造方法,若有显示定义的构造方法,默认的构造方法就会失效。
- 单例模式(Singleton):保证一个类仅有一个实例,并提供一个访问它的全局访问点。
*通常我们可以让一个全局变量使得一个对象被访问,但它不能防止你实例化多个对象。一个最好的办法就是:让类自身负责保存它的唯一实例。这个类可以保证没有其他实例可以被创建,并且它可以提供一个访问该实例的方法。 - 单例模式的意图是使得类的一个对象成为系统中的唯一实例。
好处
- 单例模式可以保证唯一的实例。
- 单例模式因为类本身封装了它的唯一实例,这样它可以严格地控制客户怎么样访问他以及何时访问他。简单来说就是对唯一实例的受控访问。
多线程中的单例
- 在多线程程序中,多个线程同时,值得注意的是同时访问单例的构造方法,会有可能造成创建多个实例的。所以我们需要把进程加一把锁来处理。lock 是确保当一个线程位于代码的临界区时,另一个线程不进去临界区。如果其他线程试图进入锁定的代码,则它将一直等待,知道该对象被释放。
- 双重锁定
我们不用让线程每次都加锁,而只是在实例未被创建的时候再加锁处理。同时也能保证多线程的安全。这种做法被称为Double-Check Locking(双重锁定)。 - 饿汉式单例类:静态初始化的方式是在自己被加载时就将自己实例化。
- 懒汉式单例类:要在第一次被引用时,才会将自己实例化。
- 懒汉式和饿汉式比较
由于类一加载就实例化对象,所以要提前占用系统资源。而懒汉式又会面临着多线程访问的安全性问题,需要做双重锁定这样的处理才能保证安全。从C#语言的角度来讲,饿汉式单例类已经满足我们的需求了。
使用单例的情况
- 类中只能有一个实例,而且必须从一个为人熟知的访问点对其进行访问。
- 这个唯一的实例只能够通过子类化进行扩展,而且扩展的对象不会破坏客户端代码。
在Cocoa Touch中使用单例模式
- 使用UIApplication类。这是框架中最为常用的一个单例类,他提供了一个控制并协调iOS应用程序的集中点。
- 使用UIAccelerometer类。该类让应用程序可以进行注册,以接收来自iOS设备内置的加速计的加速度相关数据。应用程序会收到三维空间中沿主轴的线性加速度变化,可以使用这一数据监测设备的当前方向和当前方向的瞬间变化。
- 使用NSFileManager类。
例子
Singleton.h
//
// Singleton.h
// SingletonDemo
//
// Created by zhanggui on 15/8/6.
// Copyright (c) 2015年 zhanggui. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface Singleton : NSObject
+(instancetype)sharedInstance;
@end
Singleton.m
//
// Singleton.m
// SingletonDemo
//
// Created by zhanggui on 15/8/6.
// Copyright (c) 2015年 zhanggui. All rights reserved.
//
#import "Singleton.h"
@implementation Singleton
+(instancetype)sharedInstance {
static Singleton *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
@end
上面这种方式是最安全也是最有效的创建单例的方式。不可能去创建两个实例,而且使100%的线程安全。
总结
- 几乎在任何的应用程序中,单例模式都极为常用,并不只限于iOS应用程序开发。
- 只要应用程序需要用集中式的类来协助其服务,这个类就应生成单一的实例,而不是多个实例。