美文网首页
iOS 单例模式

iOS 单例模式

作者: jiangzz | 来源:发表于2021-07-13 17:25 被阅读0次

前言:

单例模式的意思就是只有一个实例。单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类称为单例类。

要点:

显然单例模式的要点有三个;一是某个类只能有一个实例;二是它必须自行创建这个实例;三是它必须自行向整个系统提供这个实例。

一、单例的优缺点

1.单例的优点(主要优点)

实例控制:Singleton 会阻止其他对象实例化其自己的 Singleton 对象的副本,从而确保所有对象都访问唯一实例
因为其上面的特点,对于项目中的个别场景的传值,存储状态等等更加方便

2.单例的缺点(主要缺点)
单例实例一旦创建,对象指针是保存在静态区的,那么在堆区分配空间只有在应用程序终止后才会被释放
单例不能继承

二、单例的几种写法

OC

1.静态指针方式(单线程模式单例)

///.h
@interface SingleExample : NSObject

+ (instancetype)sharedInstance;

@property (nonatomic, copy) NSString *order_id;

@end

///.m
#import "SingleExample.h"

@implementation SingleExample

+ (instancetype)sharedInstance{
    static SingleExample *myInstance = nil;
    if(myInstance == nil){
        myInstance = [[SingleExample alloc]init];
    }
    return myInstance;
}
@end

///测试
SingleExample *model = [SingleExample sharedInstance];
model.order_id = @"0001";
NSLog(@"------%@-------",model.order_id)

2.多线程加锁单例

/**
dispatch_once 无论使用多线程还是单线程,都只执行一次
GCD创建单例不仅可以解决多条线程的线程安全问题,也能保证性能,是官方荐的方式。
dispatch_once主要是根据onceToken的值来决定怎么去执行代码。
当onceToken = 0时,线程执行dispatch_once的block中代码
当onceToken =- 1时,线程跳过dispatch_once的block中代码不执行
当onceToken为其他值时,线程被阻塞,等待onceToken值改变

dispatch_once执行的流程
当线程调用shareInstance,此时onceToken = 0,调用block中的代码。此onceToken的值变为72。
当其他线程再调用shareInstance方法时,onceToken的值已经是72了,线程阻塞。
当block线程执行完block之后,onceToken变为-1.其他线程不再阻塞,跳过block。
下次再调用shareInstance时,block已经为-1.直接跳过block。
 */

///.h
@interface SingleExample : NSObject

+ (SingleExample *)shareInstance;

@property (nonatomic, copy) NSString *order_id;

@end

@implementation ShareManage

///.m
+ (SingleExample *) shareInstance {
    
    static SingleExample * single = nil;
    static dispatch_once_t onceToken ;
    
    NSLog(@"onceToken开始::::::%ld",onceToken);
    dispatch_once(&onceToken, ^{
        
        shareInstance =[[SingleExample alloc]init];
        NSLog(@"onceToken执行中::::::%ld",onceToken);
       // [NSThread sleepForTimeInterval:10];
        
    }) ;
    NSLog(@"onceToken执行结束::::::%ld",onceToken);
    return shareInstance;
    
}

@end

///测试
SingleExample *model = [SingleExample shareInstance];
model.order_id= @"0002";
NSLog(@"------%@-------",model.order_id)

3.单例的健壮性

///.h
@interface ShareManage : NSObject

+ (instancetype)shareManager;

@property (nonatomic, strong) NSString *NAME;

@end

///.m
#import "ShareManage.h"

@interface ShareManage()<NSCopying,NSMutableCopying>

@end

static ShareManage *manager = nil;

@implementation ShareManage

+ (instancetype)shareManager{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [[self alloc]init];
        //不是使用alloc方法,而是调用[[super allocWithZone:NULL] init]
        //已经重载allocWithZone基本的对象分配方法,所以要借用父类(NSObject)的功能来帮助出处理底层内存分配的杂物
    });
    return manager;
}

///用alloc返回也是唯一实例
+ (id)allocWithZone:(struct _NSZone *)zone{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [super allocWithZone:zone];
    });
    return manager;
}

///对对象使用copy也是返回唯一实例
- (nonnull id)copyWithZone:(nullable NSZone *)zone {
    return manager;
}

 ///对对象使用mutablecopy也是返回唯一实例
- (nonnull id)mutableCopyWithZone:(nullable NSZone *)zone {
    return manager;
}
/*
 
 当static关键字修饰局部变量时,只会初始化一次且在程序中只有一份内存
 allocWithZone mutablecopyWithZone 这个类遵守<NSCopying,NSMutableCopying>协议
 如果_instance = [self alloc] init];创建的话,
 将会和-(id) allocWithZone:(struct _NSZone *)zone产生死锁。
 dispatch_once中的onceToken线程被阻塞,等待onceToken值改变。
 当用alloc创建对象、以及对对象进行copy mutableCopy也是返回唯一实例
 
 */
@end

///测试
ShareManage *manage = [ShareManage shareManager];
manage.NAME = @"测试单例,输出名称";
NSLog(@"------%@-------",manage.NAME)

Swift

1.最简单的 全局变量方法(“单行单例”方法) 通过 static 关键字创建

class SingletonOne {
    static let sharedInstance = SingletonOne()
    private init() {} 
    //切记私有化初始化方法,防止外部通过init直接创建实例。
}

2.严格单例模式 继承自 NSObject

class SingletonClass: NSObject {

    static let shared = SingletonClass()
    
    // Make sure the class has only one instance
    // Should not init or copy outside
    private override init() {}
    
    override func copy() -> Any {
        return self // SingletonClass.shared
    }
    
    override func mutableCopy() -> Any {
        return self // SingletonClass.shared
    }
    
    // Optional
    func reset() {
        // Reset all properties to default value
    }
}
/**
静态属性 shared 持有唯一的实例,对外公开。

重载 init() 方法,使其对外不可见,不可以在外部调用,防止在外部创建实例。

重载 copy()、mutableCopy() 方法,返回 self,防止在外部复制实例。这里也可以返回 SingletonClass.shared,效果是一样的,因为只有一个实例。只有 shared 能调用 copy()、mutableCopy() 方法,那么 self 就是 shared。写 self,代码比较简洁。

单例一旦创建,一直持有,不能手动销毁,但可以重置数据。如果需要的话,可以添加一个重置数据的方法 reset()。例如,当前用户退出登录,需要把当前用户实例的所有属性重置为默认值,防止数据错误。

*/

3.不继承自 NSObject

class SingletonClass2 {
    
    static let shared = SingletonClass2()
    
    // Make sure the class has only one instance
    // Should not init outside
    private init() {}
    
    // Optional
    func reset() {
        // Reset all properties to default value
    }
}
///不继承自 NSObject 的类没有 copy()、mutableCopy() 方法,不需要重载。

4.方法内定义静态常量

class SingleFour :NSObject{
 
    var tValue = "df"

    static var sharedInstance : SingleFour {
        struct Static {
            static let instance : SingleFour = SingleFour()
        }
        return Static.instance
    }
}

或

class ShareManage: NSObject {

    var tValue = "df"

    class var shareOnce : ShareManage {
        struct tOnce {
            static let instance = ShareManage()
        }
        return tOnce.instance
    }

}

///测试
ShareManage.sharedInstance.tValue = "1001"
print("123456789" + ShareManage.sharedInstance.tValue)

5.全局的常量

let single = SingleSix()
 
class SingleSix {
 
    var tValue = "df"
    class var sharedInstance : SingleSix {
        return single
    }
}

///测试
ShareManage.sharedInstance.tValue = "1001"
print("123456789" + ShareManage.sharedInstance.tValue)

6.使用GCD技术实现的单例模式 使用dispatch_once可以保证其中的代码只执行一次

/**
class SwiftSingleton {
    class var shared: SwiftSingleton {
        dispatch_once(&Inner.token) {
            Inner.instance = SwiftSingleton()
        }
        return Inner.instance!
    }
    struct Inner {
        static var instance: SwiftSingleton?
        static var token: dispatch_once_t = 0
    }
}
///swift3.0之后 dispatch_once_t、dispatch_once不可用。修改为下面代码
*/

var sharedInstance : ShareManage  {
    
    struct Inner {

        static var instance: ShareManage?
        static var token = {0}()
    }
    
    _ = Inner.token
    
    return Inner.instance!
 
}


class ShareManage {
    static let sharedInstance: ShareManage = { ShareManage() }()
    
    var shareName = ""
}

///测试
ShareManage.sharedInstance.shareName = "100"
print("123456789" + ShareManage.sharedInstance.shareName)

三、系统中的单例

UIApplication(应用程序实例)
NSNotificationCenter(消息中心):
NSFileManager(文件管理):
NSUserDefaults(应用程序设置):
NSURLCache(请求缓存):
NSHTTPCookieStorage(应用程序cookies池):

END

相关文章

  • 单例

    iOS单例模式iOS之单例模式初探iOS单例详解

  • iOS 单例模式

    关于单例模式的详解,看完这几篇,就完全了然了。iOS 单例模式iOS中的单例模式iOS单例的写法

  • iOS 单例模式 or NSUserDefaults

    本文内容:iOS的单例模式NSUserDefaults的使用总结:iOS单例模式 and NSUserDefaul...

  • 单例模式 Singleton Pattern

    单例模式-菜鸟教程 iOS中的设计模式——单例(Singleton) iOS-单例模式写一次就够了 如何正确地写出...

  • 【设计模式】单例模式

    学习文章 iOS设计模式 - 单例 SwiftSingleton 原理图 说明 单例模式人人用过,严格的单例模式很...

  • iOS模式设计之--创建型:1、单例模式

    iOS模式设计之--1、单例模式

  • iOS单例模式容错处理

    ios 单例模式容错处理 1、单例模式的使用和问题解决 在ios开发的过程中,使用单例模式的场景非常多。系统也有很...

  • 谈一谈iOS单例模式

    这篇文章主要和大家谈一谈iOS中的单例模式,单例模式是一种常用的软件设计模式,想要深入了解iOS单例模式的朋友可以...

  • iOS知识梳理3:设计模式

    iOS有哪些常见的设计模式?单例模式/委托模式/观察者模式/MVC模式 单例模式 单例保证了应用程序的生命周期内仅...

  • 单例对象

    iOS单例模式(Singleton)单例模式的意思就是:只有一个实例;单例模式确保每个类只有一个实例,而且自行实例...

网友评论

      本文标题:iOS 单例模式

      本文链接:https://www.haomeiwen.com/subject/wefspltx.html