C++设计模式一览
2014-05-22 18:20
274 查看
单例模式
单例模式的使用场景:
单例模式也称为单件模式、单子模式,可能是使用最广泛的设计模式。其意图是保证一个类仅有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。有很多地方需要这样的功能模块,如系统的日志输出,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的生命周期为:产生于第一次调用,结束于程序结束,结束时自动调用析构函数来释放对象,并且保证了整个程序运行中只有一个对象
这样,就可以在该类的析构函数中处理释放资源的操作,比如释放文件,设备等资源。
关于内存释放的描述,参考于网上的解释,个人觉得在使用单例模式的时候,不存在内存泄露的问题,上面使用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类用户提供锁操作
原文参考
/article/1422737.html工厂模式
工厂模式使用背景
工厂模式是创建型模式中最典型的模式,主要是用来创建对象,减少我们在使用某个对象时的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(); } };
总结:
简单工厂模式:一个抽象产品类,可以派生出多个具体产品类。
一个工厂类,可以创建出多个产品类的实例
工厂方法模式:
一个抽象产品类,可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类只能创建一个具体产品类的实例。
抽象工厂模式:
多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类可以创建多个具体产品类的实例。
区别:
工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。
工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。
参考博文:
/article/1361779.htmlhttp://www.cnblogs.com/hegezhou_hot/archive/2010/11/30/1892227.html
Builder创建者模式
Builder模式旨在将对象的创建与表示分离,使得同样的构建过程可以创建不同的表示。当创建的多个对象需要使用同一创建过程,但是具体创建细节不同时,非常适用于Builder模式。
下面以组装一台汽车为例。组装一辆汽车都需要经过上引擎、轮子等过程,但是不同品牌的汽车使用的部件是不一样的。满足于构建过程相同,而构造细节不同的模式
#include <string> #include <iostream> 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 <iostream> #include <string> 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方法内采用直接内存拷贝的方式,而避免使用调用构造函数,这才能将其优势显示出来。
返回顶部
相关文章推荐
- state设计模式学习, 一个C++的实现
- C++设计模式之Singleton
- 常见设计模式的解析和实现(C++)之十二-ChainOfResponsibility模式
- 常见设计模式的解析和实现(C++)之七-Bridge模式
- 常见设计模式的解析和实现(C++)之八-Composite模式
- C++设计模式:Singleton的模板实现之一
- 常见设计模式的解析和实现(C++)之三-Builder模式
- 常见设计模式的解析和实现(C++)之十四-Command模式
- 常见设计模式的解析和实现(C++)之十五-Observer模式
- 常见设计模式的解析和实现(C++)之五-Singleton模式
- 设计模式解析的C++实现
- 设计模式:浅谈行为模式State(C/C++ C#)
- C++设计模式之Adapter
- 常见设计模式的解析和实现(C++)之十三-FlyWeight模式
- 常见设计模式的解析和实现(C++)之十八-Iterator模式
- C++实现网络服务器命令模式(设计及模板实现)
- C++设计模式之Adapter
- 常见设计模式的解析和实现(C++)之二十-Visitor模式
- 常见设计模式的解析和实现(C++)之十-Proxy模式
- 常见设计模式的解析和实现(C++)之四-Prototype模式