外国优秀设计网站推荐,建设电子商务网站必须首先确定的是,wordpress破解登录密码破解,企业信用信息公示系统网址gsxtiOS学习 前言单例模式的概念单例模式的优缺点单例模式的两种模式懒汉模式饿汉模式单例模式的写法 总结 前言
在一开始学习OC的时候#xff0c;我们初步接触过单例模式。在学习定时器与视图移动的控件中#xff0c;我们初步意识到单例模式的重要性。对于我们需要保持的控件我们初步接触过单例模式。在学习定时器与视图移动的控件中我们初步意识到单例模式的重要性。对于我们需要保持的控件使用单例可以有效的防止再次创建而造成的bug现在我们深入学习一下单例模式。 单例模式的概念
如果一个类有且仅有一个实例并提供一个类方法供全局调用那么这个类就被称为单例类。 而使用这样的类就是单例模式。
单例模式的优缺点
优点
全局访问单例模式确保一个类只有一个实例并提供全局访问点方便在整个应用中共享数据或功能。节省资源由于只创建一个实例可以减少内存开销避免重复创建相同对象。控制实例化通过私有构造函数防止外部代码创建多个实例确保数据一致性。
缺点
隐藏依赖使用单例可能导致代码中隐藏的依赖关系增加了代码的耦合性降低了可测试性。难以扩展单例模式不易于扩展若需要改变实例的行为可能需要修改单例类的代码。线程安全问题在多线程环境下单例的实现需要特别注意线程安全若处理不当可能导致数据不一致。
单例模式的两种模式
实现单例模式我们需要保证永远只创建一个实例。那么创建实例的方法有四种因此我们需要分别改写这四种方法。
通过alloc init创建通过类方法创建通过copy创建通过mutableCopy 创建
懒汉模式
懒汉模式的主要特点是在需要时才会创建单例对象的实例而不是在程序启动时就立即创建。通过延迟对象的初始化来节省资源和提高性能。 如同名字除了在用到时“懒得创建”。 #import Singletion.himplementation Singletion
static id instance nil;(instancetype)allocWithZone:(struct _NSZone *)zone
{if(instance nil) {synchronized (self) {if(instance nil) {instance [super allocWithZone:zone];}}}return instance;
}(instancetype)mySingletion {if (instance nil) {synchronized (self) {instance [[self alloc] init];}}return instance;
}-(id)copyWithZone:(NSZone *)zone
{return instance;
}-(id)mutableCopyWithZone:(NSZone *)zone
{return instance;
}
验证代码
#import UIKit/UIKit.h
#import AppDelegate.h
#import Foundation/Foundation.h
#import Singletion.hint main(int argc, char * argv[]) {NSString * appDelegateClassName;autoreleasepool {// Setup code that might create autoreleased objects goes here.appDelegateClassName NSStringFromClass([AppDelegate class]);Singletion *singletion [Singletion mySingletion];Singletion *copySingletion [singletion copy];Singletion *mutableCopySingletion [singletion mutableCopy];Singletion *allocSingletion [[Singletion alloc] init];NSLog(%d,singletion copySingletion);NSLog(%d,singletion mutableCopySingletion);NSLog(%d,singletion allocSingletion);NSLog(%d,copySingletion mutableCopySingletion);}return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}结果
饿汉模式
饿汉模式的特点是在一开始就创建单例对象的实例提前创建单例对象并且分配好内存空间。使用时就是将该对象拿出来。 #import Singletion.himplementation Singletion
static id instance nil; (void)load{instance [[self alloc] init];
}(instancetype)mySingletion {if (instance nil) {synchronized (self) {instance [[self alloc] init];}}return instance;
}(instancetype)allocWithZone:(struct _NSZone *)zone
{if(instance nil) {synchronized (self) {if(instance nil) {instance [super allocWithZone:zone];}}}return instance;
}-(id)copyWithZone:(NSZone *)zone
{return instance;
}-(id)mutableCopyWithZone:(NSZone *)zone
{return instance;
}
重点就是在程序加载开始就创建这个单例对象。
判断代码
#import UIKit/UIKit.h
#import AppDelegate.h
#import Foundation/Foundation.h
#import Singletion.hint main(int argc, char * argv[]) {NSString * appDelegateClassName;autoreleasepool {// Setup code that might create autoreleased objects goes here.appDelegateClassName NSStringFromClass([AppDelegate class]);Singletion *singletion [Singletion sharedInstance];Singletion *copySingletion [singletion copy];Singletion *mutableCopySingletion [singletion mutableCopy];Singletion *allocSingletion [[Singletion alloc] init];NSLog(%d,singletion copySingletion);NSLog(%d,singletion mutableCopySingletion);NSLog(%d,singletion allocSingletion);NSLog(%d,copySingletion mutableCopySingletion);}return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}
运行结果 单例模式的写法
原本在书中的写法为 这种方法在多线程调用时并不能保证成功使用单例模式。
(instancetype)mySingleton {if (instance nil) {instance [[self alloc] init];}return instance;
}从而我们使用加锁来保证多线程中也可以创建单例类
加锁写法
(instancetype)allocWithZone:(struct _NSZone *)zone
{if(instance nil) {synchronized (self) {if(instance nil) {instance [super allocWithZone:zone];}}}return instance;
}还有一个GCD的写法换一种加锁方式。 GCD写法 (instancetype)allocWithZone:(struct _NSZone *)zone {static dispatch_once_t onceToken 0;dispatch_once(onceToken, ^{instance [super allocWithZone:zone];});return instance;
}GCD加锁相比于第二个加锁方法在性能上更有优势。因为它省去了锁操作代替的是大量的原子操作直接利用了 lock 的汇编指令靠底层 CPU 指令来支持的。
dispatch_once 主要是根据 onceToken 的值来决定怎么去执行代码。
1.当 onceToken 0 时线程执行 dispatch_once 的 block 中代码
2.当 onceToken -1 时线程跳过 dispatch_once 的 block 中代码不执行
3.当 onceToken 为其他值时线程被阻塞等待 onceToken 值改变。
当线程调用mySingleton方法时此时 onceToken 0调用 block 中的代码此时 onceToken 其他值。 当其他线程再调用 mySingleton 方法时onceToken为其他值线程阻塞。当 block 线程执行完 block之后onceToken -1其他线程不再阻塞跳过 block。下次再调用mySingleton方法 时 block 已经为-1直接跳过 block。 总结
饿汉模式和懒汉模式都是实现单例模式的一种方法各有优点。 饿汉模式用空间换取时间先创建出来这样再调用时就不需要花时间判断节省运行时间。 懒汉模式用时间换空间如果一直不需要创建这个单例则节约了内存空间。一旦进行判断是否需要创建该实例则会浪费判断的时间。 我们还需要关注这里通过加锁的方式创建单例以保证线程安全。这是因为如果到了多线程的环境里多个进程同时访问单例该单例模式也有可能返回不同的对象。因此我们可以通过加锁和GCD模式来实现保证线程安全。