生活随笔
收集整理的這篇文章主要介紹了
iOS设计模式 ——单例模式详解以及严格单例模式注意点
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
一、我們常用的單例有哪些?
[[UIApplication sharedApplication] statusBarStyle];//系統中的單例模式,通過它獲取到狀態欄的style
[NSNotificationCenter defaultCenter] addObserver:<#(nonnull id)#> selector:<#(nonnull SEL)#> name:<#(nullable NSString *)#> object:<#(nullable id)#>];//defaultCenter從控制中心類中獲取到了單例的實例
[NSUserDefaults standardUserDefaults] setObject:<#(nullable id)#> forKey:<#(nonnull NSString *)#>]; [NSFileManager defaultManager];
從這些常用的單例可以發現,通過這些常用的單例方法來獲取到這個類的唯一實例,再在這個實例的基礎上進行相關的操作、作業。
二、單例模式基本原理
單例模式,一般用來管理某些資源的,用來管理某個對象,他這個對象持有了某些核心資源,這個資源可以全局共享。大部分情況我們使用單例模式就是為了共享信息 ,一般作為管理中心。
缺點是因為他共享了信息,就破壞了設計模式中的最少知識原則,產生了耦合,破壞了封裝性,。但是在解決問題的過程中,這種不好的地方也是可以忽略的。
下面我們來自己寫一個單例的例子,詳細的講一下對單例的理解。創建一個UserInfoManagerCenter的類
仿照系統的單例形式自己寫這個類方法。
#import <Foundation/Foundation.h>@interface UserInfoManagerCenter : NSObject@property (nonatomic ,strong) NSString *name;@property (nonatomic ,strong) NSString *age;+ (instancetype)managerCenter;@end
在UserInfoManagerCenter.m中實現這個方法
#import "UserInfoManagerCenter.h"@implementation UserInfoManagerCenter/** * ?常規做法 */+(instancetype)managerCenter{ ? ?static UserInfoManagerCenter *center = nil;//靜態變量持有這個對象 ? ?if (center == nil) { ? ? ? ?center = [[UserInfoManagerCenter alloc]init]; ? ?} ? ?return center;}@end
但是這種方法并不好,當多個地方調用這個方法時,會造成同時都進入到alloc init。
因此,使用第二種方法
#import "UserInfoManagerCenter.h"@implementation UserInfoManagerCenter/** * ?第二種方案,用dispatch_once來解決競爭問題 */+(instancetype)managerCenter{ ? ?static UserInfoManagerCenter *center = nil; ? ?static dispatch_once_t onceToken; ? ?dispatch_once(&onceToken, ^{ ? ? ? ?center = [[UserInfoManagerCenter alloc]init]; ? ?}); ? ?return center;}@end
當然還有第三種方法 ? ?--- ??initialize的作用,同一個類初始化時只會調用一次。
#import "UserInfoManagerCenter.h"static UserInfoManagerCenter *center = nil;@implementation UserInfoManagerCenter/** * 第三種方法,每個類調用任意方法時都會提前調用的這個initialize方法,initialize的作用,同一個類初始化時只會調用一次。所以說我們將單例寫在這個地方也是沒有問題的,但是不推薦 */+(void)initialize{ if (self == [UserInfoManagerCenter class]) { center = [[UserInfoManagerCenter alloc]init]; }}+(instancetype)managerCenter{ return center;}@end
讓我們來驗證下,然后在AppDelegate里賦值
#import "AppDelegate.h"#import "UserInfoManagerCenter.h"@interface AppDelegate ()@end@implementation AppDelegate- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { UserInfoManagerCenter *center = [UserInfoManagerCenter managerCenter]; center.name = @"YUSIR"; return YES;}
在ViewController的viewDidLoad里取出值查看結果
#import "ViewController.h"#import "UserInfoManagerCenter.h"@interface ViewController ()@end@implementation ViewController- (void)viewDidLoad { [super viewDidLoad]; UserInfoManagerCenter * center = [UserInfoManagerCenter managerCenter]; NSLog(@"name:%@",center.name);}
三種方法結果能打印出來,單例實現了資源共享
三、嚴格單例模式的注意點
下面來簡單談談嚴格的單例模式,有三個問題可能需要注意一下:
1.如何防止繼承;
2.如何確保實例對象只出現一個;
3.防止實例對象被釋放掉;
第一個問題,防止繼承
+(instancetype)managerCenter{ static UserInfoManagerCenter *center = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ center = [[UserInfoManagerCenter alloc]init]; }); //防止子類重載調用使用 NSString *classString = NSStringFromClass([self class]);//獲取當前類的名字 if ([classString isEqualToString:@"UserInfoManagerCenter"] == NO) { NSParameterAssert(nil); //填nil會導致程序崩潰 } return center;}
創建一個子類繼承自UserInfoManagerCenter,調用managerCenter會直接崩潰,比較簡單這里就不截圖了
第二個問題,如何確保實例對象只出現一個。除了類方法之類還有init方法,只能重寫他的init方法,來實現init方法失效
static UserInfoManagerCenter *center = nil;@implementation UserInfoManagerCenter+(instancetype)managerCenter{ static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ center = (UserInfoManagerCenter *)@"UserInfoManagerCenter"; center = [[UserInfoManagerCenter alloc]init]; }); //防止子類重載調用使用 NSString *classString = NSStringFromClass([self class]);//獲取當前類的名字 if ([classString isEqualToString:@"UserInfoManagerCenter"] == NO) { NSParameterAssert(nil); //填nil會導致程序崩潰 } return center;}- (instancetype)init { NSString *string = (NSString *)center; if ([string isKindOfClass:[NSString class]]== YES && [string isEqualToString:@"UserInfoManagerCenter"]) { self = [super init]; if (self) { //防止子類重載調用使用 NSString *classString = NSStringFromClass([self class]);//獲取當前類的名字 if ([classString isEqualToString:@"UserInfoManagerCenter"] == NO) { NSParameterAssert(nil); //填nil會導致程序崩潰 } } return self; }else { return nil; }}
第三個,由于現在是項目是ARC開發的,是引用計數管理的。無法重載release,可以跳過這個問題。
當然嚴格的單例模式,只要注意避免類似情況發生,就可以不用過多考慮這些負擔了。
總結
以上是生活随笔為你收集整理的iOS设计模式 ——单例模式详解以及严格单例模式注意点的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。