網站首頁 學習教育 IT科技 金融知識 旅遊規劃 生活小知識 家鄉美食 養生小知識 健身運動 美容百科 遊戲知識 綜合知識
當前位置:趣知科普吧 > 綜合知識 > 

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

欄目: 綜合知識 / 發佈於: / 人氣:3.21W
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);

}

}

Tags:模式 單例 ios