【OC】單例模式

文章目錄

  • 前言
  • 概念
  • 優缺點
    • 優點
    • 缺點
  • 兩種使用模式
    • 懶漢模式
      • 實現代碼
      • 運行結果
    • 餓漢模式
      • 實現代碼
      • 運行結果
  • 在自定義類方法時的幾種常見寫法
  • 總結

前言

在之前我們已經學習過單例模式的有關內容,但是只是最簡單的單例,無法勝任多線程或者稍微多一點的情況便無法確定單例的唯一性,于是更深度的學習了單例模式

概念

單例模式的定義:一個類有且只有一個實例,并且自行實例化向整個系統提供。

即他用自己內部方法進行創立的唯一對象實例,并且可以被全局訪問

優缺點

優點

  1. 全局訪問

    單例模式就像一個全局變量,可以通過統一的入口來獲取,并可以更方便的共享一些全局的數據與資源

  2. 節省資源

    只創建一次實例,避免了頻繁的new/alloc

  3. 控制實例化過程

    通過私有函數和靜態方法控制對象的唯一性,保持了數據的唯一性

缺點

  1. 隱藏依賴,增加耦合

    很多地方都直接訪問單例,形成一種“隱形依賴”,在更改或替換單例時導致牽一發而動全身

  2. 不利于擴展與測試

    通常通過靜態方法提供實例,全局固定,難以繼承或替換

  3. 多線程安全問題

    在并發環境下,如果單例初始化沒有處理好線程安全(比如加鎖或使用 dispatch_once),可能會創建出多個實例,違背單例的初衷,尤其在懶漢式單例實現中,這一點必須特別小心。

兩種使用模式

一般來說,創建一個單例之后要保證唯一實例的話要分別改寫四種方法,即:用alloc init創建;通過類方法創建;通過copy創建;通過mutableCopy創建

而在改寫這四種方法時按照創建時間主要分為兩種,即懶漢模式和餓漢模式

懶漢模式

即在我們需要用到這個單例的時候,我們才開始創建這個唯一的實例,通過延遲對象的初始化來節省資源和提高性能,這種也是比較常用的創建單例模式的方式:

實現代碼

+ (instancetype)sharedInstance {static Singletion *instance = nil;static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{instance = [[super allocWithZone: NULL] init];});return instance;
}
+ (instancetype)allocWithZone:(struct _NSZone *)zone {return [self sharedInstance];
}
- (id)copyWithZone:(NSZone *)zone {return self;
}
- (id)mutableCopyWithZone:(NSZone *)zone {return self;
}
#import <Foundation/Foundation.h>
#import "Singletion.h"int main(int argc, const char * argv[]) {@autoreleasepool {Singletion *s1 = [Singletion sharedInstance];Singletion *s2 = [Singletion sharedInstance];Singletion *s3 = [s1 copy];Singletion *s4 = [s1 mutableCopy];NSLog(@"%d", s1 == s2);NSLog(@"%d", s1 == s3);NSLog(@"%d", s2 == s3);NSLog(@"%d", s1 == s4);}return 0;
}

這里涉及到了一個新的東西,即dispatch_once,經學長博客學習,發現其主要是按照onceToken的值來進行代碼執行的

  1. onceToken = 0時,線程執行里面block中的代碼
  2. onceToken = -1時,線程跳過block里的代碼不執行
  3. onceToken = 其他值時,線程即會被阻塞,等待onceToken的值改變

當線程調用mySingleton方法時,此時 onceToken = 0,調用 block 中的代碼,此時 onceToken =其他值。
當其他線程再調用 mySingleton 方法時,onceToken為其他值,線程阻塞。當 block 線程執行完 block之后,onceToken = -1,其他線程不再阻塞,跳過 block。下次再調用這個初始化方法時, block 已經為-1,直接跳過 block

運行結果

請添加圖片描述

餓漢模式

餓漢模式指的是我們在一開始加載時就直接創建這個單例對象的實例,使用時再把這個對象拿出來,用到的這種方式不是特別常用,因為性能不如上面的懶漢模式

餓漢有個優點就是,因為這個實例在加載時就已經創建完成,所以其不存在多線程創建的問題,因而一般來說也不需要用dispatch_once或者加鎖方法,當然用了也行,不過好像是有點多余的寫法

實現代碼

#import "Singletion.h"@implementation Singletionstatic Singletion* instance = nil;+ (void)load {instance = [[super allocWithZone: NULL] init];//NSLog(@"Singleton");
}
+ (instancetype)sharedInstance {return instance;
}
+ (instancetype)allocWithZone:(struct _NSZone *)zone {if (!instance) {instance = [super allocWithZone: zone];}return instance;
}
- (id)copyWithZone:(NSZone *)zone {return self;
}
- (id)mutableCopyWithZone:(NSZone *)zone {return self;
}
@end
int main(int argc, const char * argv[]) {@autoreleasepool {Singletion *s1 = [Singletion sharedInstance];Singletion *s2 = [Singletion sharedInstance];Singletion *s3 = [s1 copy];Singletion *s4 = [s1 mutableCopy];NSLog(@"%d", s1 == s2);NSLog(@"%d", s1 == s3);NSLog(@"%d", s2 == s3);NSLog(@"%d", s1 == s4);}return 0;
}

運行結果

請添加圖片描述

在自定義類方法時的幾種常見寫法

首先我們知道餓漢一般是不需要擔心其線程安全問題的,所以一般只考慮懶漢模式的幾種寫法,主要有兩種

在懶漢模式中一般有兩種寫法,分別是GCD和加鎖的寫法,GCD的寫法是現在寫法更推薦的,因為其性能極快且第一次使用后后續基本無開銷,而使用加互斥鎖@synchronized的方式性能較慢,且每次使用時都有鎖的開銷所以不常用

GCD的寫法在上面已經給出,下面我給出使用加鎖方式的代碼:

static Singletion* instance = nil;
+ (id)sharedInstance {if (instance == nil) {@synchronized (self) {if (instance == nil) {instance = [[super allocWithZone: NULL] init];}}}return instance;
}
+ (id)allocWithZone:(struct _NSZone *)zone {if (instance == nil) {@synchronized (self) {if (!instance) {instance = [[super allocWithZone: NULL] init];}}}return instance;
}
- (id)copyWithZone:(NSZone *)zone {return self;
}
- (id)mutableCopyWithZone:(NSZone *)zone {return self;
}

總結

總而言之,懶漢模式一般用于需要延遲加載實例的情況,可以節省資源,提高性能,但是需要考慮線程安全的問題;餓漢模式適用于需要簡單實現和線程安全的情況,但是不支持延遲加載,在程序開始時便加載完成了

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

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

相關文章

機器學習(七)決策樹-分類

一 概念1 決策節點通過條件判斷而進行分支選擇的節點。將樣本的屬性值&#xff0c;也就是特征值與決策節點上的值進行比較&#xff0c;從而判斷它的流向。2 葉子節點沒有子節點的節點&#xff0c;表示最終的決策結果。3 決策樹的深度所有節點的最大層次數決策樹具有一定的層次結…

IT 服務管理的新格局:從工單系統到一體化 ITSM 平臺

企業 IT 部門的角色轉變在過去&#xff0c;IT 部門更多被視為“技術支持”&#xff0c;主要負責設備維護和故障處理。但隨著數字化轉型加速&#xff0c;IT 已經成為業務連續性和創新的重要推動力。從客戶體驗到數據安全&#xff0c;從業務敏捷到成本控制&#xff0c;IT 服務管理…

創建一個Spring Boot Starter風格的Basic認證SDK

文章目錄前言設計思路SDK實現步驟1. 創建SDK Maven項目&#xff08;sdk目錄&#xff09;2. 實現配置類3. 實現認證邏輯4. 實現攔截器5. 實現自動配置6. 創建spring.factories文件使用方集成步驟1. 引入SDK依賴2. 配置Application屬性3. 創建測試接口4. 測試接口訪問SDK擴展功能…

mybatis處理統計sql進度丟失問題

如何處理統計sql進度丟失 SELECT sum(decimal_column) AS sum_value FROM your_table如上sql執行時沒有問題&#xff0c;在數據庫可視工具可以正常顯示&#xff0c;但是在mybatis執行時&#xff0c;卻出現解決辦法 使用轉 decimal 控制精度 SELECT CAST(SUM(decimal_column) A…

全球首款!科聰控制器獲德國 TüV 萊茵功能安全認證

近日&#xff0c;浙江科聰控制技術有限公司&#xff08;以下簡稱"科聰"&#xff09;的安全移動機器人控制器MSC5000榮獲全球權威認證機構德國萊茵TV集團&#xff08;TV Rheinland&#xff09;頒發的功能安全認證證書。這款控制器是全球首款通過SIL3、PLe 認證的移動機…

pureadmin的動態路由和靜態路由

在 PureAdmin&#xff08;基于 Vue3 的后臺管理框架&#xff09;中&#xff0c;靜態路由和動態路由是實現路由管理的兩種方式&#xff0c;主要區別在于路由的定義時機、加載方式和靈活性&#xff0c;具體區別如下&#xff1a; 1. 靜態路由 定義方式&#xff1a;路由規則在代碼中…

第3章:CPU實戰

1. Linux操作系統CPU平均負載 以前我們總認為CPU使用率和CPU平均負載是一樣的&#xff0c;負載高了就是CPU使用率提高。但是到底是什么情況呢&#xff1f; 1.1. CPU的平均負載 單位時間內 系統處于 可運行狀態 和不可中斷狀態 的平均進程數&#xff0c;就是平均活躍進程數&a…

【Vue3】06-利用setup編寫vue(1)

其它篇章&#xff1a; 1.【Vue3】01-創建Vue3工程 2.【Vue3】02-Vue3工程目錄分析 3.【Vue3】03-編寫app組件——src 4.【Vue3】04-編寫vue實現一個簡單效果 5.【Vue3】05-Options API和Composition API的區別 6.【Vue3】06-利用setup編寫vue&#xff08;1&#xff09; 7.【Vue…

UDS NRC速查

目錄 NRC 一、通用NRC(0x10~0x5F) 二、數據相關NRC(0x70~0x8F) 三、會話與狀態NRC 注意事項 UDS中的NRC(Negative Response Code)即否定響應碼,用于在診斷通信中表示服務端無法成功執行客戶端請求的原因。以下是一些常用的UDS NRC碼及其含義: HEX Name Description 01 …

【AI論文】多模態大型語言模型的視覺表征對齊

摘要&#xff1a;通過視覺指令微調訓練的多模態大型語言模型&#xff08;MLLMs&#xff09;在各類任務中均取得了優異表現&#xff0c;然而在以視覺為中心的任務&#xff08;如物體計數或空間推理&#xff09;中&#xff0c;其性能仍存在局限。我們將這一差距歸因于當前主流的純…

SKywalking Agent配置+Oracle監控插件安裝指南

SKywalking Agent配置Oracle監控插件安裝指南前言&#xff1a; SkyWalking Elasticsearch8 容器化部署指南 Skywalking版本&#xff1a;V10.2.0 Skywalking Agent版本&#xff1a;V9.4.0 Skywalking Agent下載地址&#xff1a;Downloads | Apache SkyWalking 插件下載地址&…

ES相關問題匯總

問題一&#xff1a;關于【QueryBuilder對象】和【Query String語法】查詢時底層運行方式和結果的差異

5. STM32 時鐘系統分配

文章目錄下述將以stm32f407 為例1. 時鐘系統及頻率分析2. 時鐘配置下述將以stm32f407 為例 1. 時鐘系統及頻率分析 上述STM32F4時鐘系統圖解析入下&#xff1a; STM32F407 系列微控制器&#xff08;基于 Cortex-M4 內核&#xff0c;帶 FPU&#xff09;的工作頻率配置如下&…

《從 0 建立測試開發認知:先搞懂 “是什么”,再學 “怎么做”》

&#x1f525;個人主頁&#xff1a;草莓熊Lotso &#x1f3ac;作者簡介&#xff1a;C研發方向學習者 &#x1f4d6;個人專欄&#xff1a; 《C知識分享》《Linux 入門到實踐&#xff1a;零基礎也能懂》《數據結構與算法》《測試開發實戰指南》《算法題闖關指南》 ??人生格言&a…

net::ERR_EMPTY_RESPONSE

net::ERR_EMPTY_RESPONSE表現解決表現 Java后端封裝一個接口&#xff0c;透傳前端參數&#xff0c;請求到其他模塊服務 本地開發環境聯調時是沒有問題&#xff0c;測試環境上報錯 1.前端報錯&#xff0c;F12檢查&#xff0c;network上的請求&#xff0c;返回response選項中為空…

在線多功能環境音生成器

https://oltool.cc/toolbox/huanjingyins.html 關于環境音生成器介紹&#xff1a; 1、本工具可以混合各種聲音&#xff0c;比如下雨聲&#xff0c;打雷聲&#xff0c;海浪聲&#xff0c;鳥叫以及蟲鳴聲等&#xff0c;生成新的環境聲。 2、定時器&#xff1a;可以設置倒計時&…

本地電腦映射端口到外網訪問的開啟方法和注意事項,內網服務提供跨網使用簡單操作實現

在計算機網絡中&#xff0c;端口映射是一項重要的技術&#xff0c;它允許外網用戶訪問局域網內的特定設備或服務。當我們在本地電腦搭建部署項目應用后&#xff0c;就可以通過映射端口的方式&#xff0c;簡單快速穩定的提供互聯網訪問服務。以下將詳細介紹如何開啟電腦映射端口…

Java 大視界 -- Java 大數據在智能醫療健康檔案數據分析與個性化健康管理中的應用(410)

Java 大視界 -- Java 大數據在智能醫療健康檔案數據分析與個性化健康管理中的應用&#xff08;410&#xff09;引言&#xff1a;正文&#xff1a;一、2023 年 6 月智能醫療健康檔案的核心落地需求&#xff08;政策 業務雙驅動&#xff09;1.1 政策倒逼的數據應用痛點&#xff…

微服務架構的基石:Nacos全方位解析與Java實戰指南

引言在云原生與微服務浪潮席卷而來的今天&#xff0c;服務的治理與配置的管理變得前所未有的復雜。一個個單一的應用被拆分為數十甚至上百個微服務&#xff0c;如何讓這些服務輕松地發現彼此&#xff1f;如何在不重啟應用的情況下動態調整所有服務的參數&#xff1f;這些問題直…

IDA pro 生成idapro.hexlic

先安裝IDA pro&#xff0c;安裝好后&#xff0c;把根目錄中的 ida32.dll和ida.dll賦值到python文件腳本同目錄中&#xff0c;如圖。 直接運行py import json import hashlib import os from datetime import datetime, timedelta import platform import winregname input(&…