单例模式也称为单件模式、单子模式,可能是使用最广泛的设计模式。其意图是保证一个类仅有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。有很多地方需要这样的功能模块,如系统的日志输出,GUI应用必须是单鼠标,MODEM的联接需要一条且只需要一条电话线,操作系统只能有一个窗口管理器,一台PC连一个键盘。
class CSingleton {
private:
CSingleton() { }
private:
static CSingleton* m_sl;
public:
static CSingleton* GetInstance()
{
if (m_sl == NULL) {
m_sl = new CSingleton();
}
return m_sl;
}
};
CSingleton *CSingleton::m_sl = NULL;
该实现中很明显有 new 操作,一般用户new,那么就需要用户来手动delete,防止内存泄露。 因为将构造函数定义为了private,所以至始至终不能生成一个对象,系统也就没有机会来调用析构函数,因此在析构函数中来delete就行不通了。当然,可以定义一个与GetInstance()相对应的方法ReleaseInstance(),在该方法中调用 delete 是可行。但这也需要手动来调用 ReleaseInstance() ,粗心的用户可能会忘记调用。
所以,采用 static 成员对象的方法来绕开 new-delete 方式,将内存的释放交还给操作系统
class CSingleton {
private:
CSingleton(){}
CSingleton(const CSingleton &s);
CSingleton &operator=(CSingleton &s);
public:
static CSingleton * GetInstance()
{
static CSingleton m_s; //程序结束时,会自动回收1&
return &m_s;
}
~CSingleton(){}
};
将拷贝构造跟赋值重载声明为private,防止用户生成对象
这样,就可以在该类的析构函数中处理释放资源的操作,比如释放文件,设备等资源。
关于内存释放的描述,参考于网上的解释,个人觉得在使用单例模式的时候,不存在内存泄露的问题,上面使用static对象来完成自动释放也没有什么作用,因为既然使用单例,那么程序始终只有该类的一份实例,程序结束时,回收了所有的资源,堆/栈/文件 等,也就没有必要自己显示的来释放内存了!(欢迎网友对此观点的批评指正)
在多线程程序中,有可能几个线程同时调用了 GetInstance() 函数,几个线程同时判定 m_sl 为空,后果就是,这几个线程都会调用 new 操作,产生了过个类的实例,违背了单例模式设计的初衷。因此需要一种线程安全的实现方法。
class Lock {
private:
pthread_mutex_t m_mutex;
public:
Lock(const pthread_mutex_t &mutex) : m_mutex(mutex)
{
pthread_mutex_lock(&m_mutex); //lock
}
~Lock()
{
pthread_mutex_unlock(&m_mutex);
}
};
class CSingleton {
private:
CSingleton()
{
cout << "CSingleton::CSingleton()" << endl;
}
public:
static CSingleton * GetInstance()
{
//判断两次是为了将锁操作放在内部,避免每次GetInstance的时候都加锁,提升效率
if (instance == NULL) {
pthread_mutex_init(&mutex, NULL);
Lock lock(mutex);
if (instance == NULL) {
instance = new CSingleton();
}
}
return instance;
}
public:
static pthread_mutex_t mutex;
private:
static CSingleton *instance;
};
CSingleton *CSingleton::instance = NULL;
pthread_mutex_t CSingleton::mutex;
在上面的代码中使用了互斥锁来保证只有一个线程可以申请到资源,从而实例化一个类。Lock类用户提供锁操作
http://blog.csdn.net/hackbuteer1/article/details/7460019
工厂模式是创建型模式中最典型的模式,主要是用来创建对象,减少我们在使用某个对象时的new() 操作。通过工厂来完成对象的创建,这样不但提供了统一创建对象的入口,而且对于程序的可维护和可测试性都有很大的提高,有利于程序扩展。常见的三种工厂模式有:简单工厂、工厂方法、抽象工厂。
简单工厂模式在工厂中根据传入的类型判断,来生产不同的产品
//定义产品类
class BaseCar
{
public:
virtual void show() = 0;
};
class BMWCarr : public BaseCar
{
public:
void show()
{
cout << "宝马汽车" << endl;
}
};
class BenzCar : public BaseCar
{
public:
void show()
{
cout << "奔驰汽车" << endl;
}
};
//定义一个简单工厂
class SimpleFactory
{
public:
BaseCar* CreateCar(const char* type)
{
if (strcasecmp(type, "BMW") == 0) {
return new BMWCar();
} else if (strcasecmp(type, "Benz") == 0) {
return new BenzCar();
} else {
return NULL;
}
}
};
简单工厂的缺点:增加新的产品类型时,就需要修改工厂类。 这就违反了开放封闭原则:软件实体(类、模块、函数)可以扩展,但是不可修改。
工厂方法模式是将工厂做一次抽象,将产品的生产延迟到工厂子类中去完成,当有新的产品需要生产时,只需要派生一个子工厂来完成生产,扩展极其方便。
class IFactory
{
public:
virtual BaseCar* CreateCar() = 0;
};
class BMWFactory : public IFactory
{
public:
BMWCar* CreateCar()
{
return new BMWCar();
}
};
class BenzFactory : public IFactory
{
public:
BenzCar* CreateCar()
{
return new BenzCar();
}
};
工厂方法模式的缺点:每种产品对应一个工厂,当产品过多时,需要大量的工厂来生产,造成了类膨胀。
抽象工厂模式是对工厂模式的进一步抽象与集中。抽象体现在每个工厂生产一个品牌的产品,集中体现在在一个工厂中可以生产多个同品牌的产品
class BusinessCar : public BaseCar
{
virtual void show() = 0;
};
class SportCar : public BaseCar
{
virtual void show() = 0;
};
class BMWBusinessCar : public BusinessCar
{
public:
void show()
{
cout << "宝马商务汽车" << endl;
}
};
class BMWSportCar : public SportCar
{
public:
void show()
{
cout << "宝马跑车" << endl;
}
};
class BenzBusinessCar : public BusinessCar
{
public:
void show()
{
cout << "奔驰商务汽车" << endl;
}
};
class BenzSportCar : public SportCar
{
public:
void show()
{
cout << "奔驰跑车" << endl;
}
};
// 定义一个抽象工厂
class IFactory
{
public:
virtual BusinessCar* CreateBusinessCar() = 0;
virtual SportCar* CreateSportCar() = 0;
};
class BMWFactory : public IFactory
{
public:
BusinessCar* CreateBusinessCar()
{
return new BMWBusinessCar();
}
SportCar* CreateSportCar()
{
return new BMWSportCar();
}
};
class BenzFactory : public IFactory
{
public:
BusinessCar* CreateBusinessCar()
{
return new BenzBusinessCar();
}
SportCar* CreateSportCar()
{
return new BenzSportCar();
}
};
简单工厂模式:
一个抽象产品类,可以派生出多个具体产品类。
一个工厂类,可以创建出多个产品类的实例
工厂方法模式:
一个抽象产品类,可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类只能创建一个具体产品类的实例。
抽象工厂模式:
多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类可以创建多个具体产品类的实例。
区别:
工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。
工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。
http://blog.csdn.net/wuzhekai1985/article/details/6660462
http://www.cnblogs.com/hegezhou_hot/archive/2010/11/30/1892227.html
Builder模式旨在将对象的创建与表示分离,使得同样的构建过程可以创建不同的表示。
当创建的多个对象需要使用同一创建过程,但是具体创建细节不同时,非常适用于Builder模式。
下面以组装一台汽车为例。组装一辆汽车都需要经过上引擎、轮子等过程,但是不同品牌的汽车使用的部件是不一样的。满足于构建过程相同,而构造细节不同的模式
#include
#include
using namespace std;
class Car
{
public:
string GetWheel()
{
return m_wheel;
}
void SetWheel(const string& wheel)
{
m_wheel = wheel;
}
string GetEngine()
{
return m_engine;
}
void SetEngine(const string& engine)
{
m_engine = engine;
}
string GetBland()
{
return m_bland;
}
void SetBland(const string& bland)
{
m_bland = bland;
}
void PrintCarInfo()
{
cout << m_bland << "配置信息:" << endl;
cout << " 轮胎:" << m_wheel << endl;
cout << " 引擎:" << m_engine << endl;
}
private:
string m_wheel;
string m_engine;
string m_bland;
};
//ICarBuilder类,便是提对外接口,该接口内部实现同一过程的组装
class ICarBuilder
{
public:
Car* Build()
{
m_car = new Car;
SetBland();
BuildWheel();
BuildEngine();
return m_car;
}
protected:
virtual void SetBland() = 0;
virtual void BuildWheel() = 0;
virtual void BuildEngine() = 0;
protected:
Car* m_car;
};
//Builder构造子类实现具体的构造细节,但是都采用了继承至 ICarBuilder 类的构造过程
class BMWBuilder : public ICarBuilder
{
protected:
void SetBland()
{
m_car->SetBland("宝马汽车");
}
void BuildWheel()
{
m_car->SetWheel("米奇林");
}
void BuildEngine()
{
m_car->SetEngine("奔驰");
}
};
class BenzBuilder : public ICarBuilder
{
protected:
void SetBland()
{
m_car->SetBland("奔驰汽车");
}
void BuildWheel()
{
m_car->SetWheel("韩泰");
}
void BuildEngine()
{
m_car->SetEngine("三菱");
}
};
int main()
{
BMWBuilder bmwBuilder;
BenzBuilder benzBuilder;
Car *bmw, *benz;
bmw = bmwBuilder.Build();
benz = benzBuilder.Build();
bmw->PrintCarInfo();
benz->PrintCarInfo();
delete bmw;
delete benz;
return 0;
}
参考文章:
http://www.cnblogs.com/bastard/archive/2011/11/21/2257625.html
/********************************************************************
* 原型模式
********************************************************************
* 实现原理:根据一个基础类对象,调用clone方法复制出多个同类型对象
* 注意:使用原型模式,需要关注深拷贝问题
********************************************************************/
#include
#include
using namespace std;
class WorkExperience
{
public:
WorkExperience()
{
}
WorkExperience(const string& company, const string& worktime)
{
this->company = company;
this->worktime = worktime;
}
string GetCompany()
{
return company;
}
void SetCompany(const string& company)
{
this->company = company;
}
string GetWorkTime()
{
return worktime;
}
void SetWorkTime(const string& worktime)
{
this->worktime = worktime;
}
private:
string company;
string worktime;
};
class PersonalInfo
{
public:
PersonalInfo()
{
}
PersonalInfo(const string& name, const string& sex, int age)
{
this->name = name;
this->sex = sex;
this->age = age;
}
string GetName()
{
return name;
}
void SetName(const string& name)
{
this->name = name;
}
string GetSex()
{
return sex;
}
void SetSex(const string& sex)
{
this->sex = sex;
}
int GetAge()
{
return age;
}
void SetAge(int age)
{
this->age = age;
}
private:
string name;
string sex;
unsigned int age;
};
/* 定义一个简历原型 */
class Resume
{
public:
virtual Resume* Clone() = 0;
void SetPersonalInfo(const string& name, const string& sex, int age)
{
personalInfo->SetName(name);
personalInfo->SetSex(sex);
personalInfo->SetAge(age);
}
void SetWorkExperience(const string& company, const string& worktime)
{
workExperience->SetCompany(company);
workExperience->SetWorkTime(worktime);
}
void PrintResume()
{
cout << "个人信息:" << endl;
cout << " 姓名:" << personalInfo->GetName() << "\t性别:" << personalInfo->GetSex() << "\t年龄:" << personalInfo->GetAge() << endl;
cout << "工作经验:" << endl;
cout << " 公司名称:" << workExperience->GetCompany() << "\t工作时间:" << workExperience->GetWorkTime() << endl;
}
protected:
PersonalInfo* personalInfo;
WorkExperience* workExperience;
};
class ResumeA : public Resume
{
public:
ResumeA()
{
personalInfo = new PersonalInfo;
workExperience = new WorkExperience;
}
ResumeA(const ResumeA& resume)
{
personalInfo = new PersonalInfo;
personalInfo->SetName(resume.personalInfo->GetName());
personalInfo->SetSex(resume.personalInfo->GetSex());
personalInfo->SetAge(resume.personalInfo->GetAge());
workExperience = new WorkExperience;
workExperience->SetCompany(resume.workExperience->GetCompany());
workExperience->SetWorkTime(resume.workExperience->GetWorkTime());
}
Resume* Clone()
{
return new ResumeA(*this);
}
};
int main()
{
ResumeA* pr1 = new ResumeA;
pr1->SetPersonalInfo("张三", "男", 20);
pr1->SetWorkExperience("腾讯科技", "2004~2008");
pr1->PrintResume();
ResumeA* pr2 = (ResumeA*)pr1->Clone();
delete pr1;
pr2->SetPersonalInfo("李四","女",18);
pr2->SetWorkExperience("阿里巴巴", "2008~2012");
pr2->PrintResume();
delete pr2;
return 0;
}
上面例子中的clone方法只是简单的调用了复制拷贝构造函数来完成对象的克隆,原型模式的优势并不能得到很好的体现。当需要克隆的数据量较大时,如果在clone方法内采用直接内存拷贝的方式,而避免使用调用构造函数,这才能将其优势显示出来。
返回顶部