標籤:java io 檔案 2014 cti div 代碼 line
? ?單例模式算是設計模式中比較簡單的一種吧,設計模式不是只針對某種程式設計語言,在C++, Java, PHP等其他OOP語言也有設計模式,筆者初接觸設計模式是通過《漫談設計模式》瞭解的。這本書中是用java寫的,個人感覺拜讀完這本書以後雖然有不理解的地方但還是收穫蠻大的。上面提到依賴注入,控制翻轉的時候,沒大看懂,當學習到Strut,Spring, Hibernate的東西的時候才略懂略懂。不過在23種設計模式裡面單例模式還是算比較好理解的, 那麼在OC中又是怎麼來表示單例模式的呢?下面會結合著lusashi的代碼,理解一下OC中得單例模式。
? ?首先得瞭解什麼是單例模式,用大白話說,單例模式就是在程式中這個類只對應著一個執行個體,這就是單例模式,單例模式一般用全域靜態對象來實現。下面我們會建立一個產生單例的類SingletonClass,在實現檔案中定義各種方法來實現我們的單例模式。
? ?1.單例模式一般用全域靜態對象來實現,所以我們在SingletonClass.m中定義一個靜態全域變數是少不了的
12 |
//定義靜態全域變數 static SingletonClass *single = nil; |
? ?2.上面的靜態變數是定義在實現檔案中的所以是私人的,要想擷取該類的執行個體得有個getInstance方法來擷取執行個體,在給靜態變數分配記憶體空間之前首先要判斷是否已經分配過啦,確保單例,如果分配過了就不分配了。
123456789 |
//擷取靜態全域對象 +(id)getInstance { //如果沒有產生對象,則為靜態全域變數分配記憶體 if (single == nil) { single = [[SingletonClass alloc] init]; } return single; } |
? ?
? ?3.為了防止使用者通過alloc和new來執行個體化對象,因此我們要對類方法allcoWithZone進行重寫
12345678 |
//防止通過alloc或者new來建立新的對象我們要重寫allocWithZone +(id)allocWithZone:(NSZone *)zone { if (single == nil) { single = [[super allocWithZone:zone] init]; } return single; } |
? ?4.為了防止使用者把單例進行深淺拷貝,我們需要重寫copyWithZone方法和mutableCopyWithZone方法,在重寫方法之前我們的單例類必須遵循協議NSCoping和NSMutableCoping協議
? ?遵循協議代碼如下:
123456789 |
@interface SingletonClass : NSObject<NSCopying, NSMutableCopying> //單例中擷取單例對象的方法 +(id) getInstance; //單例測試方法 -( void ) singletonFunction; @end |
? ?重寫copyWithZone方法
12345 |
//為了防止通過copy來建立新的執行個體我們要重寫copyWithZone; -(id)copyWithZone:(NSZone *)zone { return self; } |
? ?重寫mutableCopyWithZone方法
1234 |
-(id)mutableCopyWithZone:(NSZone *)zone { return self; } |
?5.防止使用者把建立的單例dealloc,我們需要重寫retainCount方法
12345 |
//重寫retainCount方法,防止被dealloc,返回最大值 -(NSUInteger) retainCount { return NSUIntegerMax; } |
?6. 重寫release,autorelease, retain方法
12345678910111213141516 |
//重寫retain,引用計數不變 -(id) retain { return self; } //重寫release -(oneway void ) release { } //重寫autorelease -(id) autorelease { return self; } |
?至此我們的單例模式基本建立完畢,下面開始我們的測試吧;
?在main函數中的代碼如下:
12345678910111213141516171819 |
//單例模式的測試 SingletonClass *single1 = [SingletonClass getInstance]; SingletonClass *single2 = [SingletonClass new ]; SingletonClass *single3 = [[SingletonClass alloc] init]; SingletonClass *single4 = [single1 copy]; SingletonClass *single5 = [single1 mutableCopy]; SingletonClass *single6 = [single1 retain]; [single1 release]; [single1 singletonFunction]; NSLog(@ "single_retainCount = %lu" , single1.retainCount); //輸出地址 NSLog(@ "getInstance single1_P = %p" , single1); NSLog(@ "new single2_P = %p" , single2); NSLog(@ "allo single3_P = %p" , single3); NSLog(@ "copy single4_P = %p" , single4); NSLog(@ "mutableCopy single5_P = %p" , single5); NSLog(@ "retain single6_P = %p" , single6); |
? ?運行結果如下:
12345678 |
2014-08-07 16:04:44.207 Memory[20664:303] singleton Ps: 我是單例模式中得測試方法!! 2014-08-07 16:04:44.207 Memory[20664:303] single_retainCount = 18446744073709551615 2014-08-07 16:04:44.207 Memory[20664:303] getInstance single1_P = 0x100204690 2014-08-07 16:04:44.208 Memory[20664:303] new single2_P = 0x100204690 2014-08-07 16:04:44.208 Memory[20664:303] allo single3_P = 0x100204690 2014-08-07 16:04:44.208 Memory[20664:303] copy single4_P = 0x100204690 2014-08-07 16:04:44.209 Memory[20664:303] mutableCopy single5_P = 0x100204690 2014-08-07 16:04:44.209 Memory[20664:303] retain single6_P = 0x100204690 |
? ? ?單例的地址是不變的。