设计模式 之美 -- 单例模式
生活随笔
收集整理的這篇文章主要介紹了
设计模式 之美 -- 单例模式
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
為什么要使用單例?
一個類只允許創建一個對象或者實例。
背景簡介:使用多線程并發訪問同一個類,為了保證類的線程安全,可以有兩種方法:
- 將該類定義為單例模式,即該類僅允許創建一個實例
- 為該類的成員函數添加類級別的鎖
舉例:
一個向指定文件寫入日志的類,為了保證該類并發調用時寫入文件的日志不會覆蓋,需執行以上操作。
單例模式的幾種經典的實現方式:
-
餓漢式
在類的加載期間,將靜態實例初始化好,所以實例的創建是線程安全的。但是這樣的方式不支持延遲加載,且每加載一個實例都會重新初始化一次,開銷較大。
-
懶漢式
懶漢模式相對于餓漢模式的優點是支持延遲加載(C++ 種的動態綁定),只有實例化的時候才知道該對象的實例。但是會導致出現頻發加鎖,釋放鎖造成效率底下 的問題。
-
雙重檢測
雙重檢測既支持延遲加載,又支持高并發的單例實現方式。
-
靜態內部類
JAVA支持的靜態內部類實現單例。這種實現方式既支持延遲加載,也支持高并發實例,實現起來也比雙重檢測簡單。
-
枚舉
最簡單的實現方式,基于枚舉實現的單例。通過枚舉類型本身的特性,保證了實例創建的線程安全性和實例的唯一性。
C語言單例模式的實現:
餓漢模式
csingleton.h
#ifndef CSINGLETON_H
#define CSINGLETON_H
#include <stdlib.h>typedef struct {void* (*ctor)(void *_self);void* (*dtor)(void *_self);void* (*createInstance)(void *self);void *instance;
} _CSingleton;extern const void *CSingleton;
void *GetInstance(void);#endif
csingleton.c
#include "csingleton.h"
#include <stdlib.h>static void *csingletonCtor(void *_self) {_CSingleton *self = _self;self->instance = _self;return self;
}static void *csingletonDtor(void *_self) {_CSingleton *self = _self;self->instance = NULL;return self;
}static void *csingletonCreateInstance(void *_self) {_CSingleton *self = _self;self->instance = _self;return self;
}static _CSingleton _csingleton = {csingletonCtor, csingletonDtor, csingletonCreateInstance, NULL
};
const void *CSingleton = &_csingleton;void *GetInstance(void) { //當調用該函數加載類的時候進行初始化if (NULL == ((_CSingleton*)CSingleton)->instance) {return csingletonCtor(CSingleton);} else {return ((_CSingleton*)CSingleton)->instance;}
}
main.c
#include "csingleton.h"
#include <stdio.h>int main(int argc, char *argv[]) {void *ps1 = GetInstance();void *ps2 = GetInstance();if (ps1 == ps2) {fprintf(stdout, "ps1 = ps2\n");}return 0;
}
懶漢模式
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <omp.h>typedef struct ID{char *name;int id_num;
}id;static id *_id = NULL;/*通過鎖進行并發訪問時線程間競爭的控制*/
static omp_lock_t lock;id *getInstance(){omp_set_lock(&lock);if(NULL != _id) {omp_unset_lock(&lock);return _id;} else {_id = (id*)malloc(sizeof(id));assert(_id != NULL);omp_unset_lock(&lock);return _id;}
}int main(int argc, char *argv[]) {omp_set_num_threads(20);//運行時的庫函數,設置運行的線程數目id * i1, *i2;omp_init_lock(&lock);{i1 = getInstance() ;i1->name = "Rong";i1->id_num = omp_get_thread_num();}{i2 = getInstance() ;i2->name = "Tao";}omp_destroy_lock(&lock);if(i1 == i2){fprintf(stdout, " i1 == i2 \n");}fprintf(stdout, "i1->name = %s, i1->score = %d\n",i1->name, i1->id_num);fprintf(stdout, "i2->name = %s, i2->score = %d\n",i2->name, i2->id_num);return 0;
}
C++實現單例模式
餓漢模式
#include <iostream>
using namespace std;class Singleon
{
private:Singleon(){cout << "Singleon()" << endl;}static Singleon* instance;
public:static Singleon* GetSingleon(){return instance;}static Singleon* Destroy(){delete instance;instance = NULL;}
};/*編譯加載類的時候即初始化,靜態成員編譯的時候即會初始化*/
Singleon* Singleon::instance = new Singleon();int main(){Singleon* sl1 = Singleon::GetSingleon();Singleon* sl2 = Singleon::GetSingleon();Singleon* sl3 = Singleon::GetSingleon();cout << sl1 << endl;cout << sl2 << endl;cout << sl2 << endl;system("pause");return 0;}
懶漢模式
#include <iostream>
using namespace std;class Singleon
{
private:Singleon(){cout << "Singleon()" << endl;}static Singleon*instrance;
public:static Singleon* GetSingleon(){if (NULL == instrance){instrance = new Singleon();cout << "對象創建成功" << endl;}else{cout << "對象已經創建成功,無須再建" << endl;}return instrance;}static Singleon* Destroy(){delete instrance;instrance = NULL;}
};/*類加載的時候不進行初始化,實例化的時候進行初始化*/
Singleon* Singleon::instrance = NULL;
int main()
{Singleon* sl1 = Singleon::GetSingleon();Singleon* sl2 = Singleon::GetSingleon();Singleon* sl3 = Singleon::GetSingleon();cout << sl1 << endl;cout << sl2 << endl;cout << sl2 << endl;system("pause");return 0;
}
總結
以上是生活随笔為你收集整理的设计模式 之美 -- 单例模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 生面麒麟boss绝杀
- 下一篇: 论文查重多少钱啊?