[GoF設計模式]Iterator模式和Singleton模式的C++實現

【Iterator模式】

提供了一種順序訪問一個聚合對象(aggregate)中各個元素,而又不需要暴露該對象的內部表示的。其關鍵是將對列表的訪問和遍歷從列表對象中分離出來並放入一個迭代器(iterator)對象中。迭代器定義個一個訪問該列元素的接口,迭代器對象負責跟蹤當前的元素;即它知道哪些元素已經遍歷過了。迭代器和列表是耦合在一起的,而且客戶對象必須知道遍歷的是一個列表而不是其他聚合結構。STL提供了iterator來遍歷各種STL中的列表。

【圖解】

以aggregate維護一個簡單的數組結構爲例子,其相應的迭代器iterator可以對該數組進行順序的訪問。一種是通過聚合對象自身提供的創建接口(CreateIterator函數,當然也是調用迭代器的構造函數),另一種是直接調用迭代器的構造函數完成。以下例子使用了類模板的繼承,在這種情況下,實現和定義最好寫在一個頭文件中即可(會避免帶來一些的問題)。

1

【程序】

 

 

 

 

【輸出】

2

 

【Singleton模式】

 

保證一個類有一個實例,並提供一個訪問它的全局訪問點。從而避免使用全局變量,全局變量有一系列的缺點,如內存佔用生命期長,名字污染等等。

(1)最簡單的單例模式在多線程環境下是線程不安全的,對此要考慮下面的兩點。

想要讓單例模式(singleton)在多線程環境下處於一個安全的狀態需要注意,對於處於多線程環境中的類,使用單例模式要考慮如下。

(2)Windows平臺上線程同步可以利用<Windows.h>中的CRITICAL_SECTION,UNIX/LINUX平臺要使用到<pthread.h>的線程同步機制,這些機制即可可以應用於對象中“臨界資源數據”。但是用於單例模式中的GetInstance函數時,由於第一次調用時,臨界邊量尚未初始化(構造函數尚未調用),因此給類對象的創建代碼(GetInstance函數中的代碼)加鎖就很報一個運行時的錯誤,是由於臨界變量的初始化是在構造函數中完成的,而此時構造函數尚未調用,所以臨界變量的初始化尚未完成。因此GetInstance的實現要考慮下面的線程安全的方式。而JAVA中可能可以考慮線程synchronized GetInstance()同步的方式進行,但是創建效率可能會受到一定的影響。

(3)對於單例模式中對象實例的獲取,採用“局部靜態變量”是線程安全的方式。其他的static成員的臨界資源的訪問,則要使用加鎖操作。

另外GoF中還提到了"單件註冊表"來解決Singleton類的子類的創建的問題。這裏不細說了,有興趣查書。

 

【圖解】

給出線程安全解釋的圖例,類圖就沒什麼必要了。

1

【程序】

 (1)線程不安全的單件模式

 

 

 (2)線程安全的單件模式[採用局部靜態方式,同時給出臨界資源的加鎖機制(Windows的,Linux的要用pthread中的東西)]

 

 (3)Main函數調用,具體的多線程的調用就不細說了。主要是Singleton模式本身。

 

【輸出】

2

可以看出地址指向的是同一個對象。局部靜態的方式創建的單件模式對象,最後的析構函數被顯示調用了。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章