當前位置:生活全書館 >

綜合知識

> 如何寫一個簡單的單例模式 ios單例模式怎麼寫

如何寫一個簡單的單例模式 ios單例模式怎麼寫

1.如何寫一個簡單的單例模式

一、基本的實現思路:

ios單例模式怎麼寫 如何寫一個簡單的單例模式

單例的實現主要是通過以下兩個步驟:

1、將該類的構造方法定義為私有方法,這樣其他處的程式碼就無法通過呼叫該類的構造方法來例項化該類的物件,只有通過該類提供的靜態方法來得到該類的唯一例項;

2、在該類內提供一個靜態方法,當我們呼叫這個方法時,如果類持有的引用不為空就返回這個引用,如果類保持的引用為空就建立該類的例項並將例項的引用賦予該類保持的引用。

二、示範如下:

1、列舉實現單例:

2、懶漢式執行緒不安全:

3、懶漢式執行緒安全:

4、餓漢式:

5、雙重校驗鎖:

6、靜態內部類:

擴充套件資料:

一、單列模式簡介:

單例模式是設計模式中最簡單的形式之一。這一模式的目的是使得類的一個物件成為系統中的唯一例項。要實現這一點,可以從客戶端對其進行例項化開始。因此需要用一種只允許生成物件類的唯一例項的機制,“阻止”所有想要生成物件的訪問。使用工廠方法來限制例項化過程。這個方法應該是靜態方法(類方法),因為讓類的例項去生成另一個唯一例項毫無意義。

二、懶漢與餓漢:

1、懶漢方式:指全域性的單例例項在第一次被使用時構建。

2、餓漢方式:指全域性的單例例項在類裝載時構建。

三、單例模式的三要點:

1、某個類只能有一個例項。

2、它必須自行建立這個例項。

3、它必須自行向整個系統提供這個例項。

四、優缺點:

1、優點:

①例項控制:單例模式會阻止其他物件例項化其自己的單例物件的副本,從而確保所有物件都訪問唯一例項。

②靈活性:因為類控制了例項化過程,所以類可以靈活更改例項化過程。

2、缺點:

①開銷:雖然數量很少,但如果每次物件請求引用時都要檢查是否存在類的例項,將仍然需要一些開銷。可以通過使用靜態初始化解決此問題。

②可能的開發混淆:使用單例物件(尤其在類庫中定義的物件)時,開發人員必須記住自己不能使用new關鍵字例項化物件。因為可能無法訪問庫原始碼,因此應用程式開發人員可能會意外發現自己無法直接例項化此類。

③物件生存期:不能解決刪除單個物件的問題。在提供記憶體管理的語言中(例如基於.NET Framework的語言),只有單例類能夠導致例項被取消分配,因為它包含對該例項的私有引用。在某些語言中(如 C++),其他類可以刪除物件例項,但這樣會導致單例類中出現懸浮引用。

參考資料:百度百科單列模式

2.開發中如何使用單例 ios

為你解答。

第一、基本概念單例模式是一種常用的軟體設計模式。在它的核心結構中只包含一個被稱為單例類的特殊類。

通過單例模式可以保證系統中一個類只有一個例項而且該例項易於外界訪問。第二、在IOS中使用單例模式的情況1.如果說建立一個物件會耗費很多系統資源,那麼此時採用單例模式,因為只需要一個例項,會節省alloc的時間2.在IOS開發中,如果很多模組都要使用同一個變數,此時如果把該變數放入單例類,則所有訪問該變數的呼叫變得很容易,否則,只能通過一個模組傳遞給另外一個模組,這樣增加了風險和複雜度第三、建立單例模式的基本步驟1.宣告一個單例物件的靜態例項,並初始化為nil2.宣告一個類的工廠方法,生成一個該類的例項,並且只會生成一個3.覆蓋allcoWithZone方法,確保使用者在alloc 時,不會產生一個多餘的物件4.實現NSCopying協議,覆蓋release,autorelease,retain,retainCount方法,以確保只有一個例項化物件5.在多執行緒的環境中,注意使用@synchronized關鍵字 [cpp] view plaincopyprint?// // UserContext.h // SingleDemo // // Created by andyyang on 9/30/13. // Copyright (c) 2013 andyyang. All rights reserved. // #import @interface UserContext : NSObject @property (nonatomic,retain) NSString *username; @property(nonatomic,retain)NSString *email; +(id)sharedUserDefault; @end [cpp] view plaincopyprint?// // UserContext.m // SingleDemo // // Created by andyyang on 9/30/13. // Copyright (c) 2013 andyyang. All rights reserved. // #import "UserContext.h" static UserContext *singleInstance=nil; @implementation UserContext +(id)sharedUserDefault { if(singleInstance==nil) { @synchronized(self) { if(singleInstance==nil) { singleInstance=[[[self class] alloc] init]; } } } return singleInstance; } + (id)allocWithZone:(NSZone *)zone; { NSLog(@"HELLO"); if(singleInstance==nil) { singleInstance=[super allocWithZone:zone]; } return singleInstance; } -(id)copyWithZone:(NSZone *)zone { NSLog(@"hello"); return singleInstance; } -(id)retain { return singleInstance; } - (oneway void)release { } - (id)autorelease { return singleInstance; } - (NSUInteger)retainCount { return UINT_MAX; }@end [cpp] view plaincopyprint?#import #import "UserContext.h" int main(int argc, const char * argv[]) { @autoreleasepool { UserContext *userContext1=[UserContext sharedUserDefault]; UserContext *userContext2=[UserContext sharedUserDefault]; UserContext *userContext3=[[UserContext alloc] init]; UserContext *userContext4=[userContext1 copy]; // insert code here。

NSLog(@"Hello, World!"); } return 0; } 在開發中我們可以利用ios提供的方法來實現單例模式:SYNTHESIZE_SINGLETON_FOR_CLASS(MyClassName);將該語句置於@implementation MyClassName聲明後,這樣你的類自動會變成單例。內容來自於richard_如風的部落格。

3.單例模式程式碼怎麼寫

單例模式(Singleton) ,屬於最常見的設計模式之一,大部分系統都會用到,目的是為了維護系統中唯一的一個例項。

可分為eager模式,示例程式碼如下: Java程式碼 1.class EagerSingleton{ 2. private static final EagerSingleton m_instance = new EagerSingleton(); 3. private EagerSingleton(){} 4. public static EagerSingleton getInstance(){ 5. return m_instance; 6. } 7.} class EagerSingleton{ private static final EagerSingleton m_instance = new EagerSingleton(); private EagerSingleton(){} public static EagerSingleton getInstance(){ return m_instance; } } 和 lazy模式,示例程式碼如下: Java程式碼 1.class LazySingleton{ 2. private static LazySingleton m_instance = null; 3. private LazySingleton(){} 4. public synchronized static getInstance(){ 5. if(m_instance == null){ 6. m_instance = new LazySingleton(); 7. } 8. return m_instance; 9. } 10.} class LazySingleton{ private static LazySingleton m_instance = null; private LazySingleton(){} public synchronized static getInstance(){ if(m_instance == null){ m_instance = new LazySingleton(); } return m_instance; } } java原始碼中,Runtime.getRuntime()就是單例的一個例子。 單例模式的精神就是整個系統中維護一個例項,推廣開來,如果在一個系統中需要維護多個示例,那麼就產生了多例模式(multiton)。

多例模式(Multiton) ,通過聚集物件了保留自身的多個示例,根據客戶端的引數返回所需要的例項。 示例程式碼如下: Java程式碼 1.class Multiton{ 2. private final int INSTANCE_SIZE = 10; 3. private static Map instances = new HashMap(INSTANCE_SIZE); 4. private String name; 5. private Multiton(){} 6. private Multiton(String name){ 7. this.name = name; 8. } 9. public synchronized static getInstance(String name){ 10. if(instances.containsKey(name)){ 11. return instances.get(name); 12. } 13. else{ 14. ins = new Multiton(name); 15. instances.put(name, ins); 16. return ins; 17. } 18. } 19.} class Multiton{ private final int INSTANCE_SIZE = 10; private static Map instances = new HashMap(INSTANCE_SIZE); private String name; private Multiton(){} private Multiton(String name){ this.name = name; } public synchronized static getInstance(String name){ if(instances.containsKey(name)){ return instances.get(name); } else{ ins = new Multiton(name); instances.put(name, ins); return ins; } } } [nextpage] 一個實用的例子就是KeyGenerator, 示例程式碼如下: Java程式碼 1.class KeyGenerator{ 2. private final int POOL_SIZE = 20; 3. private static Map instances = new HashMap(16); 4. private KeyInfo keyinfo; 5. private KeyGenerator(){} 6. private KeyGenerator(String keyName){ 7. this.keyinfo = new KeyInfo(POOL_SIZE, keyName); 8. } 9. public synchronized static getInstance(String keyName){ 10. if(instances.containsKey(keyName)){ 11. return (KeyGenerator)instances.get(keyName); 12. } 13. else{ 14. keyGen = new KeyGenerator(keyName); 15. instances.put(name, keyGen); 16. return keyGen; 17. } 18. } 19. public synzhronized int getNextKey(){ 20. return keyinfo.getNextKey(); 21. } 22. } class KeyGenerator{ private final int POOL_SIZE = 20; private static Map instances = new HashMap(16); private KeyInfo keyinfo; private KeyGenerator(){} private KeyGenerator(String keyName){ this.keyinfo = new KeyInfo(POOL_SIZE, keyName); } public synchronized static getInstance(String keyName){ if(instances.containsKey(keyName)){ return (KeyGenerator)instances.get(keyName); } else{ keyGen = new KeyGenerator(keyName); instances.put(name, keyGen); return keyGen; } } public synzhronized int getNextKey(){ return keyinfo.getNextKey(); } }。

4.單例模式程式碼怎麼寫

單例模式(Singleton) ,屬於最常見的設計模式之一,大部分系統都會用到,目的是為了維護系統中唯一的一個例項。

可分為eager模式,示例程式碼如下: Java程式碼 1.class EagerSingleton{ 2. private static final EagerSingleton m_instance = new EagerSingleton(); 3. private EagerSingleton(){} 4. public static EagerSingleton getInstance(){ 5. return m_instance; 6. } 7.} class EagerSingleton{ private static final EagerSingleton m_instance = new EagerSingleton(); private EagerSingleton(){} public static EagerSingleton getInstance(){ return m_instance; } } 和 lazy模式,示例程式碼如下: Java程式碼 1.class LazySingleton{ 2. private static LazySingleton m_instance = null; 3. private LazySingleton(){} 4. public synchronized static getInstance(){ 5. if(m_instance == null){ 6. m_instance = new LazySingleton(); 7. } 8. return m_instance; 9. } 10.} class LazySingleton{ private static LazySingleton m_instance = null; private LazySingleton(){} public synchronized static getInstance(){ if(m_instance == null){ m_instance = new LazySingleton(); } return m_instance; } } java原始碼中,Runtime.getRuntime()就是單例的一個例子。 單例模式的精神就是整個系統中維護一個例項,推廣開來,如果在一個系統中需要維護多個示例,那麼就產生了多例模式(multiton)。

多例模式(Multiton) ,通過聚集物件了保留自身的多個示例,根據客戶端的引數返回所需要的例項。 示例程式碼如下: Java程式碼 1.class Multiton{ 2. private final int INSTANCE_SIZE = 10; 3. private static Map instances = new HashMap(INSTANCE_SIZE); 4. private String name; 5. private Multiton(){} 6. private Multiton(String name){ 7. this.name = name; 8. } 9. public synchronized static getInstance(String name){ 10. if(instances.containsKey(name)){ 11. return instances.get(name); 12. } 13. else{ 14. ins = new Multiton(name); 15. instances.put(name, ins); 16. return ins; 17. } 18. } 19.} class Multiton{ private final int INSTANCE_SIZE = 10; private static Map instances = new HashMap(INSTANCE_SIZE); private String name; private Multiton(){} private Multiton(String name){ this.name = name; } public synchronized static getInstance(String name){ if(instances.containsKey(name)){ return instances.get(name); } else{ ins = new Multiton(name); instances.put(name, ins); return ins; } } } [nextpage] 一個實用的例子就是KeyGenerator, 示例程式碼如下: Java程式碼 1.class KeyGenerator{ 2. private final int POOL_SIZE = 20; 3. private static Map instances = new HashMap(16); 4. private KeyInfo keyinfo; 5. private KeyGenerator(){} 6. private KeyGenerator(String keyName){ 7. this.keyinfo = new KeyInfo(POOL_SIZE, keyName); 8. } 9. public synchronized static getInstance(String keyName){ 10. if(instances.containsKey(keyName)){ 11. return (KeyGenerator)instances.get(keyName); 12. } 13. else{ 14. keyGen = new KeyGenerator(keyName); 15. instances.put(name, keyGen); 16. return keyGen; 17. } 18. } 19. public synzhronized int getNextKey(){ 20. return keyinfo.getNextKey(); 21. } 22. } class KeyGenerator{ private final int POOL_SIZE = 20; private static Map instances = new HashMap(16); private KeyInfo keyinfo; private KeyGenerator(){} private KeyGenerator(String keyName){ this.keyinfo = new KeyInfo(POOL_SIZE, keyName); } public synchronized static getInstance(String keyName){ if(instances.containsKey(keyName)){ return (KeyGenerator)instances.get(keyName); } else{ keyGen = new KeyGenerator(keyName); instances.put(name, keyGen); return keyGen; } } public synzhronized int getNextKey(){ return keyinfo.getNextKey(); } }。

5.如何正確地寫出單例模式

當被問到要實現一個單例模式時,很多人的第一反應是寫出如下的程式碼,包括教科書上也是這樣教我們的。

1234567891011public class Singleton {private static Singleton instance;private Singleton (){}public static Singleton getInstance () {if (instance == null ) {instance = new Singleton();}return instance;}}這段程式碼簡單明瞭,而且使用了懶載入模式,但是卻存在致命的問題。當有多個執行緒並行呼叫 getInstance() 的時候,就會建立多個例項。

也就是說在多執行緒下不能正常工作。懶漢式,執行緒安全為了解決上面的問題,最簡單的方法是將整個 getInstance() 方法設為同步(synchronized)。

123456public static synchronized Singleton getInstance () {if (instance == null ) {instance = new Singleton();}return instance;}雖然做到了執行緒安全,並且解決了多例項的問題,但是它並不高效。因為在任何時候只能有一個執行緒呼叫 getInstance() 方法。

但是同步操作只需要在第一次呼叫時才被需要,即第一次建立單例例項物件時。這就引出了雙重檢驗鎖。

雙重檢驗鎖雙重檢驗鎖模式(double checked locking pattern),是一種使用同步塊加鎖的方法。程式設計師稱其為雙重檢查鎖,因為會有兩次檢查 instance == null ,一次是在同步塊外,一次是在同步塊內。

為什麼在同步塊內還要再檢驗一次?因為可能會有多個執行緒一起進入同步塊外的 if,如果在同步塊內不進行二次檢驗的話就會生成多個例項了。12345678910public static Singleton getSingleton () {if (instance == null ) { //Single Checkedsynchronized (Singleton.class) {if (instance == null ) { //Double Checkedinstance = new Singleton();}}}return instance ;}這段程式碼看起來很完美,很可惜,它是有問題。

主要在於 instance = new Singleton() 這句,這並非是一個原子操作,事實上在 JVM 中這句話大概做了下面 3 件事情。給 instance 分配記憶體呼叫 Singleton 的建構函式來初始化成員變數將instance物件指向分配的記憶體空間(執行完這步 instance 就為非 null 了)但是在 JVM 的即時編譯器中存在指令重排序的優化。

也就是說上面的第二步和第三步的順序是不能保證的,最終的執行順序可能是 1-2-3 也可能是 1-3-2。如果是後者,則在 3 執行完畢、2 未執行之前,被執行緒二搶佔了,這時 instance 已經是非 null 了(但卻沒有初始化),所以執行緒二會直接返回 instance,然後使用,然後順理成章地報錯。

我們只需要將 instance 變數宣告成 volatile 就可以了。 class Singleton {private volatile static Singleton instance; //宣告成 volatileprivate Singleton (){}public static Singleton getSingleton () {if (instance == null ) {synchronized (Singleton.class) {if (instance == null ) {instance = new Singleton();}}}return instance;}}有些人認為使用 volatile 的原因是可見性,也就是可以保證執行緒在本地不會存有 instance 的副本,每次都是去主記憶體中讀取。

但其實是不對的。使用 volatile 的主要原因是其另一個特性:禁止指令重排序優化。

也就是說,在 volatile 變數的賦值操作後面會有一個記憶體屏障(生成的彙編程式碼上),讀操作不會被重排序到記憶體屏障之前。比如上面的例子,取操作必須在執行完 1-2-3 之後或者 1-3-2 之後,不存在執行到 1-3 然後取到值的情況。

從「先行發生原則」的角度理解的話,就是對於一個 volatile 變數的寫操作都先行發生於後面對這個變數的讀操作(這裡的“後面”是時間上的先後順序)。但是特別注意在 Java 5 以前的版本使用了 volatile 的雙檢鎖還是有問題的。

其原因是 Java 5 以前的 JMM (Java 記憶體模型)是存在缺陷的,即時將變數宣告成 volatile 也不能完全避免重排序,主要是 volatile 變數前後的程式碼仍然存在重排序問題。這個 volatile 遮蔽重排序的問題在 Java 5 中才得以修復,所以在這之後才可以放心使用 volatile。

相信你不會喜歡這種複雜又隱含問題的方式,當然我們有更好的實現執行緒安全的單例模式的辦法。餓漢式 static final field這種方法非常簡單,因為單例的例項被宣告成 static 和 final 變量了,在第一次載入類到記憶體中時就會初始化,所以建立例項本身是執行緒安全的。

12345678910public class Singleton {//類載入時就初始化private static final Singleton instance = new Singleton();private Singleton (){}public static Singleton getInstance (){return instance;}}這種寫法如果完美的話,就沒必要在囉嗦那麼多雙檢鎖的問題了。缺點是它不是一種懶載入模式(lazy initialization),單例會在載入類後一開始就被初始化,即使客戶端沒有呼叫 getInstance()方法。

餓漢式的建立方式在一些場景中將無法使用:譬如 Singleton 例項的建立是依賴引數或者配置檔案的,在 getInstance() 之前必須呼叫某個方法設定引數給它,那樣這種單例寫法就無法使用了。靜態內部類 static nested class我比較傾向於使用靜態內部類的方法,這種方法也是《Effective Java》上所推薦的。

123456789public class Singleton {private static class SingletonHolder {private static final Singleton INSTANCE = new Singleton();}private Singleton (){}public 。

6.如何寫一個Singleton(單例模式)

使用執行緒單列模式獲得org.hibernate.Session物件

import org.hibernate.Session;

import org.hibernate.SessionFactory;

import org.hibernate.cfg.Configuration;

public class {

private static Configuration conf;

private static SessionFactory sf;

private static ThreadLocal<Session> tl = new ThreadLocal<Session>();

//ThreadLocal<Session>;內部是Map結構,用執行緒id作為key值,用來存放多個Session物件

static {

conf = new Configuration();

conf.configure();

sf = conf.buildSessionFactory();

}

public static Session getSession() {

Session session = tl.get();//以當前執行緒的id作為Key,取出一個Session物件

if (session == null) {

session = sf.openSession();//如果為空,則獲取一個新的Session物件,並存入tl中

tl.set(session);

}

return session;

}

public static void closeSession() {//關閉一個session

Session session = tl.get();//以當前執行緒的id作為Key,取出一個Session物件

if (session != null) {//如果不為空,怎關閉

session.close();

tl.set(null);

}

}

}

7.單例模式怎樣寫

class StringManager {

private static StringManager instance;

private Map beanMap;

private StringManager() {

beanMap = new HashMap();

}

public static StringManager getInstance() {

if (instance == null) {

instance = new StringManager();

}

return instance;

}

public Object getBean(String beanName) {

return beanMap.get(beanName);

}

}

標籤: ios 單例 模式
  • 文章版權屬於文章作者所有,轉載請註明 https://shqsg.com/zonghezhishi/nyxg1x.html