一 c++實現單例模式
保證一個類,在一個程序當中只有一個對象,只有一個實例,這個對象要禁止拷貝,注意這裏要區別於java。否者的話一個程序當中就可能出現多個對象的拷貝。
我們要禁止拷貝,需要將拷貝構造函數以及等號運算符 聲明爲私有的,並且呢不提供他們的實現。這樣子如果我們代碼裏面有拷貝構造的話,編譯時候會出錯。
僅僅這樣子是不夠的,我們必須將構造函數聲明爲私有的,這是爲了防止外部呢,任意的構造對象。
既然我們將構造函數私有化了,外部就不能通過 Singleton s1; 來定義這樣一個對象。那我們就需要提供一個接口讓外部呢得到這樣一個對象。
Singleton.cpp:
#include <iostream>
#include <memory>
using namespace std;
class Singleton
{
public:
/*這個GetInstance是靜態的由類直接調用的*/
static Singleton* GetInstance()
{
/*用這種方法會出現構造出來的這個對象什麼時候釋放的問題*/
/* if (instacne_ == NULL)
{
instacne_ = new Singleton;
}
return instacne_;*/
/* 把裸指針用智能指針來管理
* 智能指針是重載了點號運算符的,我們訪問類本身的get()方法,獲得裸指針
*/
if (!instacne_.get())
{
instacne_ = auto_ptr<Singleton>(new Singleton);
}
return instacne_.get();
}
~Singleton()
{
cout<<"~Singleton ..."<<endl;
}
private:
// 禁止拷貝--構造函數和等號運算符聲明爲私有的,並且不提供實現。
Singleton(const Singleton& other);
Singleton& operator=(const Singleton& other);
// 將構造函數說明爲私有的
Singleton()
{
cout<<"Singleton ..."<<endl;
}
/*這實際上是一個靜態的類對象,這裏僅僅是引用性說明,她的定義應該在類的外邊*/
static auto_ptr<Singleton> instacne_;
};
/*定義性說明*/
auto_ptr<Singleton> Singleton::instacne_;
int main(void)
{
//Singleton s1;
//Singleton s2;
Singleton* s1 = Singleton::GetInstance();
Singleton* s2 = Singleton::GetInstance();
//Singleton s3(*s1); // 調用拷貝構造函數
return 0;
}
Makefile:
.PHONY:clean
CPP=g++
CFLAGS=-Wall -g
BIN=test
OBJS=Singleton.o
LIBS=
$(BIN):$(OBJS)
$(CPP) $(CFLAGS) $^ -o $@ $(LIBS)
%.o:%.cpp
$(CPP) $(CFLAGS) -c $< -o $@
clean:
rm -f *.o $(BIN)
運行結果
Singleton ...
~Singleton ...
裸指針呢,用智能指針來管理靜態的一個類對象,當整個程序結束的時候,靜態對象也就被銷燬了,
那麼靜態對象的銷燬就會導致這個類對象的析構函數被調用,
這個get()方法是 智能指針提供的是吧
auto_ptr中有個get方法
還有你給的析構函數 裏面並沒有釋放 那個指針所指的資源
是程序結束的時候,由智能指針來釋放的
智能指針變量 本身不是堆區內存,
只不過說 智能指針釋放了,靜態的變量的時候會調用這個變量的析構函數
//Singleton s1;
//Singleton s2;
//Singleton s3(*s1); // 調用拷貝構造函數
這些情況下都是錯誤的,
運行結果:
g++ -Wall -g -c Singleton.cpp -o Singleton.o
Singleton.cpp: 在函數‘int main()’中:
Singleton.cpp:36:2: 錯誤: ‘Singleton::Singleton(const Singleton&)’是私有的
Singleton.cpp:59:18: 錯誤: 在此上下文中
Singleton.cpp:57:13: 警告: 未使用的變量‘s2’ [-Wunused-variable]
make: *** [Singleton.o] 錯誤 1
二,實現禁止拷貝
Nocopyable這個類如何保證禁止拷貝,她的實現和Singleton類的實現差不多。
Noncopyable.cpp:
#include <iostream>
#include <memory>
using namespace std;
class Noncopyable
{
protected:
Noncopyable() {}
~Noncopyable() {}
private:
Noncopyable(const Noncopyable&);
const Noncopyable& operator=(const Noncopyable&);
};
class Parent : private Noncopyable
{
public:
Parent()
{
}
Parent(const Parent& other) : Noncopyable(other)
{
}
};
class Child : public Parent
{
public:
//Child(const Child& other)
//{
//}
};
int main()
{
/*這兩種情況都是失敗的*/
//Parent p1;
//Parent p2(p1); // 要調用Parent拷貝構造函數,Parent構造函數又調用Noncopyable的拷貝構造函數
Child c1;
Child c2(c1);
return 0;
}
注意:
private 是實現繼承,並不是爲了繼承她的接口
public 是接口繼承
Makefile:
.PHONY:clean
CPP=g++
CFLAGS=-Wall -g
BIN=test
OBJS=Noncopyable.o
LIBS=
$(BIN):$(OBJS)
$(CPP) $(CFLAGS) $^ -o $@ $(LIBS)
%.o:%.cpp
$(CPP) $(CFLAGS) -c $< -o $@
clean:
rm -f *.o $(BIN)
運行結果:
g++ -Wall -g -c Noncopyable.cpp -o Noncopyable.o
Noncopyable.cpp: 在複製構造函數‘Parent::Parent(const Parent&)’:
Noncopyable.cpp:11:2: 錯誤: ‘Noncopyable::Noncopyable(const Noncopyable&)’是私有的
Noncopyable.cpp:23:49: 錯誤: 在此上下文中
make: *** [Noncopyable.o] 錯誤 1
這裏我們需要注意的地方是,
對於構造函數來說,如果基類有默認構造函數,即使我們沒有寫 :Noncopyable()這句話,他也是會自動調用基類的默認構造函數的,
但是拷貝構造函數就不一樣啦,如果我們沒有寫 :Noncopyable(other)這句話,是不會調用基類的拷貝構造函數的,
當然如果基類沒有默認的構造函數,那麼這個時候呢,一定要在成員列表中給出對基類構造函數的調用。
JAVA實現的單例模式:
讀取配置文件,並且實例化了一個對象,這個對象保證只有一個。
package com.ebupt.ebms.conf;
/**
* @author zling Create on 2011-3-7
* @version 1.0
*/
public class MainConfig {
private boolean useCache = true;// 是否緩存
private boolean videoConvert = false;// 是否進行視頻格式轉換
private boolean useMail = true;//是否進行郵件通知
private Integer sessionTimeOut = 3 * 60 * 1000;
private String logPath = ""; // 上傳的各種日誌的本地路徑
private String webPath = ""; // 播放任務描述文件基路徑,播放列表和資源清單均在該基路徑下
private String urlPath = ""; // 終端訪問基路徑,可爲http或ftp的基路徑
private String tomcatPath = ""; // Tomcat 服務器所在路徑
private String phoneNumber = "";// 維護人員手機號碼,多個之間用逗號分隔
private String email = "";// 維護人員郵箱地址,多個之間用逗號分隔
private String mailServer = "";// 郵箱服務器地址
private String mailAccount = "";// 郵箱賬號
private String mailPasswd = "";// 郵箱密碼
private String ltpasso = "";// 北京移動基於LTPA方式的SSO
private String sitesso = "";// 北京移動基於SiteMinder方式的SSO
private String ssourl = "";// SSO的服務路徑
private String fouraurl = "";// 4A賬號操作相關的rul
private String fouracheckurl = "";// 4A校驗相關的url
private String redirecturl = "";// 驗證成功後跳轉到的路徑
private String localfourapath = "";// 本地存放生成的4a日誌文件的路徑
private String fouraftpurl = "";// 4aftp的url
private String fouraftpport = "";// 4aftp的port
private String fouraftpname = "";// 4aftp的username
private String fouraftppwd = "";// 4aftp的password
private String fouraftpsavepath = "";// 4aftp保存文件的路徑
private String fouraftpfilename = "";// 4a要求的上傳到ftp服務器的日誌文件的名稱
private static MainConfig instance = new MainConfig();//懶人模式
public static MainConfig getInstance() {
if (instance == null)
instance = new MainConfig();
return instance;
}
public String string() {
StringBuffer sb = new StringBuffer();
sb.append("logPath : ").append(logPath).append("\n");
sb.append("webPath : ").append(webPath).append("\n");
sb.append("urlPath : ").append(urlPath).append("\n");
sb.append("tomcatPath : ").append(tomcatPath).append("\n");
sb.append("useCache : ").append(useCache).append("\n");
sb.append("useMail : ").append(useMail).append("\n");
sb.append("videoConvert : ").append(videoConvert).append("\n");
sb.append("sessionTimeOut : ").append(sessionTimeOut).append("\n");
sb.append("phoneNumber : ").append(phoneNumber).append("\n");
sb.append("email : ").append(email).append("\n");
sb.append("mailServer : ").append(mailServer).append("\n");
sb.append("mailAccount : ").append(mailAccount).append("\n");
sb.append("mailPasswd : ").append(mailPasswd).append("\n");
sb.append("ltpasso : ").append(ltpasso).append("\n");
sb.append("sitesso : ").append(sitesso).append("\n");
sb.append("ssourl : ").append(ssourl).append("\n");
sb.append("fouraurl : ").append(fouraurl).append("\n");
sb.append("fouracheckurl : ").append(fouracheckurl).append("\n");
sb.append("redirecturl : ").append(redirecturl).append("\n");
sb.append("localfourapath : ").append(localfourapath).append("\n");
sb.append("fouraftpurl : ").append(fouraftpurl).append("\n");
sb.append("fouraftpport : ").append(fouraftpport).append("\n");
sb.append("fouraftpname : ").append(fouraftpname).append("\n");
sb.append("fouraftppwd : ").append(fouraftppwd).append("\n");
sb.append("fouraftpsavepath : ").append(fouraftpsavepath).append("\n");
sb.append("fouraftpfilename : ").append(fouraftpfilename).append("\n");
return sb.toString();
}
public boolean isUseCache() {
return useCache;
}
public void setUseCache(boolean useCache) {
this.useCache = useCache;
}
public boolean isUseMail() {
return useMail;
}
public void setUseMail(boolean useMail) {
this.useMail = useMail;
}
public boolean isVideoConvert() {
return videoConvert;
}
public void setVideoConvert(boolean videoConvert) {
this.videoConvert = videoConvert;
}
public Integer getSessionTimeOut() {
return sessionTimeOut;
}
public void setSessionTimeOut(Integer sessionTimeOut) {
this.sessionTimeOut = sessionTimeOut;
}
public String getLogPath() {
return logPath;
}
public void setLogPath(String logPath) {
this.logPath = logPath;
}
public String getWebPath() {
return webPath;
}
public void setWebPath(String webPath) {
this.webPath = webPath;
}
public String getUrlPath() {
return urlPath;
}
public void setUrlPath(String urlPath) {
this.urlPath = urlPath;
}
public String getTomcatPath() {
return tomcatPath;
}
public void setTomcatPath(String tomcatPath) {
this.tomcatPath = tomcatPath;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public String getMailServer() {
return mailServer;
}
public void setMailServer(String mailServer) {
this.mailServer = mailServer;
}
public String getMailAccount() {
return mailAccount;
}
public void setMailAccount(String mailAccount) {
this.mailAccount = mailAccount;
}
public String getMailPasswd() {
return mailPasswd;
}
public void setMailPasswd(String mailPasswd) {
this.mailPasswd = mailPasswd;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getLtpasso() {
return ltpasso;
}
public void setLtpasso(String ltpasso) {
this.ltpasso = ltpasso;
}
public String getSitesso() {
return sitesso;
}
public void setSitesso(String sitesso) {
this.sitesso = sitesso;
}
public String getSsourl() {
return ssourl;
}
public void setSsourl(String ssourl) {
this.ssourl = ssourl;
}
public String getFouraurl() {
return fouraurl;
}
public void setFouraurl(String fouraurl) {
this.fouraurl = fouraurl;
}
public String getRedirecturl() {
return redirecturl;
}
public void setRedirecturl(String redirecturl) {
this.redirecturl = redirecturl;
}
public String getLocalfourapath() {
return localfourapath;
}
public void setLocalfourapath(String localfourapath) {
this.localfourapath = localfourapath;
}
public String getFouraftpurl() {
return fouraftpurl;
}
public void setFouraftpurl(String fouraftpurl) {
this.fouraftpurl = fouraftpurl;
}
public String getFouraftpport() {
return fouraftpport;
}
public void setFouraftpport(String fouraftpport) {
this.fouraftpport = fouraftpport;
}
public String getFouraftpname() {
return fouraftpname;
}
public void setFouraftpname(String fouraftpname) {
this.fouraftpname = fouraftpname;
}
public String getFouraftppwd() {
return fouraftppwd;
}
public void setFouraftppwd(String fouraftppwd) {
this.fouraftppwd = fouraftppwd;
}
public String getFouraftpfilename() {
return fouraftpfilename;
}
public void setFouraftpfilename(String fouraftpfilename) {
this.fouraftpfilename = fouraftpfilename;
}
public String getFouraftpsavepath() {
return fouraftpsavepath;
}
public void setFouraftpsavepath(String fouraftpsavepath) {
this.fouraftpsavepath = fouraftpsavepath;
}
public String getFouracheckurl() {
return fouracheckurl;
}
public void setFouracheckurl(String fouracheckurl) {
this.fouracheckurl = fouracheckurl;
}
}