iOS設計模式 ——單例模式詳解以及嚴格單例模式注意點

一、我們常用的單例有哪些?

  1. [[UIApplication sharedApplication] statusBarStyle];//系統中的單例模式,通過它獲取到狀態欄的style

  1. [NSNotificationCenter defaultCenter] addObserver:<#(nonnull id)#> selector:<#(nonnull SEL)#> name:<#(nullable NSString *)#> object:<#(nullable id)#>];//defaultCenter從控制中心類中獲取到了單例的實例
  1. [NSUserDefaults standardUserDefaults] setObject:<#(nullable id)#> forKey:<#(nonnull NSString *)#>];
  2. [NSFileManager defaultManager];

從這些常用的單例可以發現,通過這些常用的單例方法來獲取到這個類的唯一實例,再在這個實例的基礎上進行相關的操作、作業。

二、單例模式基本原理

單例模式,一般用來管理某些資源的,用來管理某個對象,他這個對象持有了某些核心資源,這個資源可以全局共享。大部分情況我們使用單例模式就是為了共享信息 ,一般作為管理中心。

缺點是因為他共享了信息,就破壞了設計模式中的最少知識原則,產生了耦合,破壞了封裝性,。但是在解決問題的過程中,這種不好的地方也是可以忽略的。


下面我們來自己寫一個單例的例子,詳細的講一下對單例的理解。創建一個UserInfoManagerCenter的類

仿照系統的單例形式自己寫這個類方法。

  1. #import <Foundation/Foundation.h>
  2. @interface UserInfoManagerCenter : NSObject
  3. @property (nonatomic ,strong) NSString *name;
  4. @property (nonatomic ,strong) NSString *age;
  5. + (instancetype)managerCenter;
  6. @end

UserInfoManagerCenter.m中實現這個方法

  1. #import "UserInfoManagerCenter.h"
  2. @implementation UserInfoManagerCenter
  3. /**
  4. * ?常規做法
  5. */
  6. +(instancetype)managerCenter
  7. {
  8. ? ?static UserInfoManagerCenter *center = nil;//靜態變量持有這個對象
  9. ? ?if (center == nil) {
  10. ? ? ? ?center = [[UserInfoManagerCenter alloc]init];
  11. ? ?}
  12. ? ?return center;
  13. }
  14. @end

但是這種方法并不好,當多個地方調用這個方法時,會造成同時都進入到alloc init。

因此,使用第二種方法

  1. #import "UserInfoManagerCenter.h"
  2. @implementation UserInfoManagerCenter
  3. /**
  4. * ?第二種方案,用dispatch_once來解決競爭問題
  5. */
  6. +(instancetype)managerCenter
  7. {
  8. ? ?static UserInfoManagerCenter *center = nil;
  9. ? ?static dispatch_once_t onceToken;
  10. ? ?dispatch_once(&onceToken, ^{
  11. ? ? ? ?center = [[UserInfoManagerCenter alloc]init];
  12. ? ?});
  13. ? ?return center;
  14. }
  15. @end

當然還有第三種方法 ? ?--- ??initialize的作用,同一個類初始化時只會調用一次。

  1. #import "UserInfoManagerCenter.h"
  2. static UserInfoManagerCenter *center = nil;
  3. @implementation UserInfoManagerCenter
  4. /**
  5. * 第三種方法,每個類調用任意方法時都會提前調用的這個initialize方法,initialize的作用,同一個類初始化時只會調用一次。所以說我們將單例寫在這個地方也是沒有問題的,但是不推薦
  6. */
  7. +(void)initialize
  8. {
  9. if (self == [UserInfoManagerCenter class]) {
  10. center = [[UserInfoManagerCenter alloc]init];
  11. }
  12. }
  13. +(instancetype)managerCenter
  14. {
  15. return center;
  16. }
  17. @end

讓我們來驗證下,然后在AppDelegate里賦值

  1. #import "AppDelegate.h"
  2. #import "UserInfoManagerCenter.h"
  3. @interface AppDelegate ()
  4. @end
  5. @implementation AppDelegate
  6. - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  7. UserInfoManagerCenter *center = [UserInfoManagerCenter managerCenter];
  8. center.name = @"YUSIR";
  9. return YES;
  10. }

在ViewController的viewDidLoad里取出值查看結果

  1. #import "ViewController.h"
  2. #import "UserInfoManagerCenter.h"
  3. @interface ViewController ()
  4. @end
  5. @implementation ViewController
  6. - (void)viewDidLoad {
  7. [super viewDidLoad];
  8. UserInfoManagerCenter * center = [UserInfoManagerCenter managerCenter];
  9. NSLog(@"name:%@",center.name);
  10. }

三種方法結果能打印出來,單例實現了資源共享

三、嚴格單例模式的注意點

下面來簡單談談嚴格的單例模式,有三個問題可能需要注意一下:

1.如何防止繼承;

2.如何確保實例對象只出現一個;

3.防止實例對象被釋放掉;

第一個問題,防止繼承

  1. +(instancetype)managerCenter
  2. {
  3. static UserInfoManagerCenter *center = nil;
  4. static dispatch_once_t onceToken;
  5. dispatch_once(&onceToken, ^{
  6. center = [[UserInfoManagerCenter alloc]init];
  7. });
  8. //防止子類重載調用使用
  9. NSString *classString = NSStringFromClass([self class]);//獲取當前類的名字
  10. if ([classString isEqualToString:@"UserInfoManagerCenter"] == NO) {
  11. NSParameterAssert(nil); //填nil會導致程序崩潰
  12. }
  13. return center;
  14. }

創建一個子類繼承自UserInfoManagerCenter,調用managerCenter會直接崩潰,比較簡單這里就不截圖了

第二個問題,如何確保實例對象只出現一個。除了類方法之類還有init方法,只能重寫他的init方法,來實現init方法失效

  1. static UserInfoManagerCenter *center = nil;
  2. @implementation UserInfoManagerCenter
  3. +(instancetype)managerCenter
  4. {
  5. static dispatch_once_t onceToken;
  6. dispatch_once(&onceToken, ^{
  7. center = (UserInfoManagerCenter *)@"UserInfoManagerCenter";
  8. center = [[UserInfoManagerCenter alloc]init];
  9. });
  10. //防止子類重載調用使用
  11. NSString *classString = NSStringFromClass([self class]);//獲取當前類的名字
  12. if ([classString isEqualToString:@"UserInfoManagerCenter"] == NO) {
  13. NSParameterAssert(nil); //填nil會導致程序崩潰
  14. }
  15. return center;
  16. }
  17. - (instancetype)init {
  18. NSString *string = (NSString *)center;
  19. if ([string isKindOfClass:[NSString class]]== YES && [string isEqualToString:@"UserInfoManagerCenter"]) {
  20. self = [super init];
  21. if (self) {
  22. //防止子類重載調用使用
  23. NSString *classString = NSStringFromClass([self class]);//獲取當前類的名字
  24. if ([classString isEqualToString:@"UserInfoManagerCenter"] == NO) {
  25. NSParameterAssert(nil); //填nil會導致程序崩潰
  26. }
  27. }
  28. return self;
  29. }else {
  30. return nil;
  31. }
  32. }

第三個,由于現在是項目是ARC開發的,是引用計數管理的。無法重載release,可以跳過這個問題。

當然嚴格的單例模式,只要注意避免類似情況發生,就可以不用過多考慮這些負擔了。







本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/248101.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/248101.shtml
英文地址,請注明出處:http://en.pswp.cn/news/248101.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

科學計算庫學習報告

numpy與matplotlib的學習隨筆 我愛代碼 import numpy as npimport matplotlib.pyplot as pltimport matplotlibmatplotlib.rcParams[font.family]SimHeimatplotlib.rcParams[font.sans-serif][SimHei]labelsnp.array([第一次,第二次,第三次,第四次,第五次,第六次])nAttr6datanp…

前端網頁 — 初始化文件

/*--------------------------初始化代碼*/ /*清除默認的margin和padding*/ * {margin: 0;padding: 0; }/*清除小圓點*/ ul {list-style: none; }/*清除a標簽默認的下劃線*/ a {text-decoration: none; }/*表格邊框合并*/ table {border-collapse: collapse; }/*去除input標簽點…

數據庫系統原理(第二章關系數據庫 )

一、關系數據庫概述 20世紀80年代后&#xff0c;在商用數據庫管理系統中&#xff0c;&#xff08; 關系模型 &#xff09;逐漸取代早 期的網狀模型和層次模型&#xff0c;成為主流數據模型 SQL3&#xff08;SQL-99&#xff09;:1999年 SQL2&#xff08;SQL-92&#xff09;&…

iOS NSMutableAttributedString常用方法總結

NSAttributedString 叫做富文本&#xff0c;是一種帶有屬性的字符串&#xff0c;通過它可以輕松的在一個字符串中表現出多種字體、字號、字體大小等各不相同的風格&#xff0c;還可以對段落進行格式化&#xff0c;一般都是對可變富文本&#xff08;NSMutableAttributedString&a…

微信小程序image bindload事件失效不觸發

1.先上代碼 <template><div :class"[img-wrapper, className]"><img :src"defaultSrc" :mode"mode" class"default-img" :hidden"loaded"><img :src"src" :mode"mode" load"…

數據可視化(BI報表的開發)第三天

20、銷售統計-布局 html結構&#xff1a; <!-- 銷售額 --><div class"sales panel"><div class"inner"><div class"caption"><h3>銷售額統計</h3><a href"javascript:;" class"active&q…

軟件開發工具(第1章:緒論)

一、 軟件開發工具的由來 計算機語言和軟件開發工具的發展和歷史 機器語言&#xff08;第一代語言&#xff09;&#xff1a;難以記憶的、無意義的、二進 制的字符串 匯編語言&#xff08;第二代語言&#xff09;針對難以記憶的、無意義的、二進 制的字符串、人們試圖用英語中具…

Swift傻傻分不清楚系列(一)常量與變量

菜鳥從零開始認識學習Swift。感謝大神們翻譯的文檔。搬到自己小黑屋里慢慢看~~~ 本頁包含內容&#xff1a; 常量和變量聲明常量和變量類型標注常量和變量的命名輸出常量和變量注釋分號 Swift 是一門開發 iOS, OS X 和 watchOS 應用的新語言。然而&#xff0c;如果你有 C 或者 …

Saiku Table展示數據合并bug修復(二十五)

Saiku Table展示數據合并bug修復 Saiku以table的形式展示數據&#xff0c;如果點擊了 非空的字段 按鈕&#xff0c;則會自動進行數據合并&#xff0c;為空的數據行以及數據列都會自動隱藏掉。 首先我們應該定位問題&#xff1a; 1.查看接口返回值&#xff0c;會發現接口返回都正…

軟件開發工具(第2章:軟件開發過程及其組織)

一、軟件開發的困難 程序員做好軟件工作的關鍵是什么&#xff1f; 關鍵是兩個轉換&#xff1a; 第一個轉換是用戶對軟件功能的理解與程序員對軟件功能的理解之間的轉換。 &#xff08;不同?業的?員對于事物的認識?法與描述?法是不同的。&#xff09; 第二個轉換要解決的是人…

數據可視化(BI報表的開發)第四天

練習題&#xff1a; 先找出字符串 ‘8587263747153203552943982’ 中出現次數最多的數字及次數&#xff0c;然后去重后并排序&#xff08;不準使用sort&#xff09;&#xff0c;使得到結果為 ‘0123456789’。 要求1&#xff1a;找到出現最多的數字和出現的次數 // 1、找出出…

Swift傻傻分不清楚系列(二)數據類型

本頁包含內容&#xff1a; 整數整數范圍IntUInt浮點數類型安全和類型推斷數值型字面量數值型類型轉換整數轉換數整數和浮點數轉換類型別名布爾值 整數 整數就是沒有小數部分的數字&#xff0c;比如42和-23。整數可以是有符號&#xff08;正、負、零&#xff09;或者無符號&…

Python打卡第四周

這一周鴿了好久&#xff0c; 因為最近在準備比賽。課程一直沒跟上。。。 今天整理完本周的知識之后休息一周復習之前的 好了。 上總結 第一天 裝飾器定義函數bar&#xff0c;在foo中調用 # def foo(): # # print(in the foo) # # bar() # # foo()def bar():print(in th…

網絡經濟與企業管理(第 1 章:企業管理概論)

一、企業的概念 什么是企業&#xff1f; 1.企業以市場為導向&#xff0c;以價值增值作為經濟活動的目的 2.企業是從事商品生產和流通的經濟組織 3.企業經營過程中要自主經營、自負盈虧、獨立核算和承擔風險&#xff0c;具有法人資格的基本經濟單位 企業發展的三個時期&#xff…

js高級 — ES6

ECMAScript 6 目標&#xff1a;學習完 ES6 可以掌握方便后續的開發&#xff0c;未來工作中大量使用 ES6 開發 ECMAScript 6 介紹ECMAScript 6 新增語法內置對象的擴展ECMAScript 6 降級處理&#xff08;學習完node再講&#xff09; 1. ECMAScript 6 介紹 ES – ECMAScript …

Swift傻傻分不清楚系列(三)元組與可選類型

本頁包含內容&#xff1a; 元組可選nilif 語句以及強制解析可選綁定隱式解析可選類型錯誤處理斷言 元組 元組&#xff08;tuples&#xff09;把多個值組合成一個復合值。元組內的值可以是任意類型&#xff0c;并不要求是相同類型。 下面這個例子中&#xff0c;(404, "Not…

去死吧!USB轉串口!!!

首先&#xff0c;這個題目有兩種歧義&#xff1a;1、USB轉232串口&#xff08;嚴格說就是這種&#xff09;&#xff01; 2、USB轉USART串口&#xff08;通常都是這么叫&#xff0c;認為就是這&#xff0c;理論上是錯誤的&#xff0c;歧義所在&#xff09;&#xff01; USB轉TTL…

IDEA微服務項目的application.yml沒有綠色葉子的解決辦法

1.今天在寫微服務項目的時候成功入坑&#xff0c;那么問題是啥呢&#xff1f;接下來和我一起走入bug的世界吧&#xff0c;讓我們看看究竟是怎么回事。 *問題描述    1.application.yml是灰色的小格子 2.實在難看 *需要解決的最終結果 1.有綠色的小葉子 解決方案上圖 1. 2. …

Ajax — 第一天

上網的目的 本質目的&#xff1a;瀏覽和消費資源 資源&#xff1a;文字、圖片、音頻、視頻…資源存在哪里&#xff1a;服務器上 服務器的概念 是負責存放和對外提供資源的電腦。它的性能比普通的計算機好太多了 客戶端 獲取和消費資源的電腦&#xff0c;叫做客戶端。 我…

linux 查看進程

1.ps 各字段含義 如果讓程序始終在后臺執行&#xff0c;即使關閉當前的終端也執行&#xff08;之前的&做不到&#xff09;&#xff0c;這時候需要nohup。 該命令可以在你退出帳戶/關閉終端之后繼續運行相應的進程。關閉中斷后&#xff0c;在另一個終端jobs已經無法看到后臺…