一 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;
}
}