C++之23种经典设计模式(一)

  • C++之23种经典设计模式(一)
    • 单例模式(Singleton)
    • 原型模式(Prototype)
    • 工厂模式(Factory)

C++之23种经典设计模式(一)

在偶然的机会里,还是决定整理一下有关程序中最为经典的GOF23种设计模式,方便以后自己查阅,此博客在于整理,下面是我参考的链接:https://blog.csdn.net/nsjim/article/details/92713881

单例模式(Singleton)

定义:
指一个类只有一个实例,且该类能自行创建这个实例的一种模式。
特点
单例模式有 3 个特点:
单例类只有一个实例对象;
该单例对象必须由单例类自行创建,其构造函数是私有的;
单例类对外提供一个访问该单例的全局访问点;
代码示例:
懒汉式单例模式:
懒汉式的特点是延迟加载,比如配置文件,采用懒汉式的方法,顾名思义,懒汉么,很懒的,配置文件的实例直到用到的时候才会加载。。。。。。

class CSingleton
{
public:
static CSingleton* GetInstance()
{  if ( m_pInstance == NULL )    m_pInstance = new CSingleton();  return m_pInstance;
}
private:  CSingleton(){};  static CSingleton * m_pInstance;  class CGarbo   //它的唯一工作就是在析构函数中删除CSingleton的实例{public:~CGarbo(){if(CSingleton::m_pInstance)delete CSingleton::m_pInstance;}};static CGarbo Garbo;  //定义一个静态成员变量,程序结束时,系统会自动调用它的析构函数
};

饿汉式:
饿汉式的特点是一开始就加载了,如果说懒汉式是“时间换空间”,那么饿汉式就是“空间换时间”,因为一开始就创建了实例,所以每次用到的之后直接返回就好了。

#include "pch.h"
#include "iostream"
using namespace std;class CSingleton
{public:static CSingleton& GetInstance();
protected:CSingleton();~CSingleton();private:static CSingleton _instance;
private://CLock m_lkMsBsGPSInfoStartFlag;bool m_bMsBsGPSInfoStartFlag;    //public:bool GetMsBsGPSInfoStart();bool SetMsBsGPSInfoStart(bool bIsStart);
};
CSingleton CSingleton::_instance;
CSingleton::CSingleton() : m_bMsBsGPSInfoStartFlag(false)
{std::cout << "enter CSingleton::CSingleton() " << endl;
}CSingleton::~CSingleton()
{std::cout << "enter CSingleton::~CSingleton() " << endl;
}CSingleton& CSingleton::GetInstance()
{std::cout << "CSingleton::GetInstance()" << endl;return _instance;
}
bool CSingleton::SetMsBsGPSInfoStart(bool bIsStart)
{m_bMsBsGPSInfoStartFlag = bIsStart;return true;
}
int main()
{return 0;
}
};

程序输出结果:


上述代码没有调用GetInstance,但是也调用了构造跟析构函数,因为单例中的_instance是

static CSingleton _instance;

在执行以下代码的时候,会去调用它的构造函数,这就是饿汉单例的模式,在你还没使用的时候就为你创建好这个单例。

CSingleton CSingleton::_instance;

在饿汉式的单例类中,其实有两个状态,单例未初始化和单例已经初始化。假设单例还未初始化,有两个线程同时调用GetInstance方法,这时执行 m_pInstance == NULL 肯定为真,然后两个线程都初始化一个单例,最后得到的指针并不是指向同一个地方,不满足单例类的定义了,所以饿汉式的写法会出现线程安全的问题!在多线程环境下,要对其进行修改。
多线程下的单例模式
这里要处理的是懒汉模式

class Singleton
{
private:  static Singleton* m_instance;  Singleton(){}  class CGarbo   //它的唯一工作就是在析构函数中删除CSingleton的实例{public:~CGarbo(){if(CSingleton::m_pInstance)delete CSingleton::m_pInstance;}};static CGarbo Garbo;  //定义一个静态成员变量,程序结束时,系统会自动调用它的析构函数
public:  static Singleton* getInstance();
};  Singleton* Singleton::getInstance()
{  if(NULL == m_instance)  {  Lock();//借用其它类来实现,如boost  if(NULL == m_instance)  {  m_instance = new Singleton;  }  UnLock();  }  return m_instance;
}

单例模式的原文链接:

https://blog.csdn.net/zhanghuaichao/article/details/79459130

原型模式(Prototype)

定义
原型(Prototype)模式的定义如下:用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。

特点
原型实例指定了要创建的对象的种类。用这种方式创建对象非常高效,根本无须知道对象创建的细节。

应用场景
对象之间相同或相似,即只是个别的几个属性不同的时候。
对象的创建过程比较麻烦,但复制比较简单的时候。
想必很多人都玩过魔兽争霸3。里面有一个非常厉害的英雄叫做剑圣。这个英雄攻击力算是最高的,而且有个听起来很叼的魔法,“剑刃风暴”,这个魔法其实效果一般,不大实用。
剑圣有一个分身的功能。这个分身各个方面和剑圣都一模一样,但是没有攻击力,也没有魔法。
如何实现这个分身的功能呢?使用原型模式。原型模式就是这么一个道理,通过现有的东西,用Clone再复制拷贝出一个或者多个。
使用原型模式理由有三:
1 这个分身是游戏过程中动态生成的。剑圣使用了这个功能就动态生成分身。
2 这个分身几乎就是剑圣的拷贝。如果重新new一个剑圣不符合游戏规则。玩过War3的人都知道一个种族只能有一个剑圣吧,如果可以有3个剑圣,让其它族怎么玩。
3 重新创建一个剑圣很麻烦,要初始化各种参数,如等级啊,攻击力啊,等等各个参数,而且这些参数要和原型一致。直接通过原型模式实现则简单。
4 便于扩展。如果分身有30%原剑圣的攻击力,那么我们直接修改Clone方法即可。对外的接口不用变更。
原文链接:

https://blog.csdn.net/faithzzf/article/details/78062779
代码示例:

#include <iostream>
#include <string>
#include <memory>
using namespace std;
class Person
{public:string name;int age;Person(string _name, int _age) :name(_name), age(_age) {}virtual ~Person() {}virtual void showMe(){cout << "I am " << name << ", and " << age << endl;}virtual Person *clone(){return new Person(*this);}
};class Boy :public Person
{public:Boy(string _name, int _age) :Person(_name, _age){}~Boy() {}virtual void showMe() override{Person::showMe();cout << "I am a boy" << endl;}virtual Person *clone() override{return new Boy(*this);}
};
class Girl :public Person
{public:Girl(string _name, int _age) :Person(_name, _age){}~Girl() {}virtual void showMe() override{Person::showMe();cout << "I am a Girl" << endl;}virtual Person *clone() override{return new Girl(*this);}
};int main()
{//创建一个boy  aPerson *a = new Boy(string("Ming"), 28);a->showMe();//创建一个Girl  bPerson *b = new Girl(string("Li"), 28);b->showMe();//克隆a--不使用原型模式的写法shared_ptr<Person> cloneA(new Boy(*dynamic_cast<Boy *>(a)));cloneA->showMe();//克隆b--使用原型模式的写法shared_ptr<Person> cloneB(b->clone());cloneB->showMe();delete b;b = nullptr;delete a;a = nullptr;delete cloneC;return 0;
}

工厂模式(Factory)

定义
工厂方法(FactoryMethod)模式的定义:定义一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类当中。这满足创建型模式中所要求的“创建与使用相分离”的特点。

我们把被创建的对象称为“产品”,把创建产品的对象称为“工厂”。如果要创建的产品不多,只要一个工厂类就可以完成,这种模式叫“简单工厂模式”,它不属于 GoF 的 23 种经典设计模式,它的缺点是增加新产品时会违背“开闭原则”。

优点
用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程;
在系统增加新的产品时只需要添加具体产品类和对应的具体工厂类,无须对原工厂进行任何修改,满足开闭原则;

缺点
每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度。

应用场景
客户只知道创建产品的工厂名,而不知道具体的产品名。如 TCL 电视工厂、海信电视工厂等。
创建对象的任务由多个具体子工厂中的某一个完成,而抽象工厂只提供创建产品的接口。
客户不关心创建产品的细节,只关心产品的品牌。
工厂模式也分为三种模式:

  1. 第一为简单工厂模式
    简单工厂模式,工厂类是创建产品的,它决定创建哪一种产品,就像领导决定采用那种技术方案样。举个例子,现在有宝马车和奔驰车两种车需要生产,但是只有一个工厂,且只能在同一时间生产一种车,这时就有工厂决定生产那种车了。例子虽然不是十分恰当,但是会其意即可。我们直接看UML类图和代码吧。

    代码示例:
#include <iostream>
using namespace std;enum CarType { BENZ, BMW };class Car//车类
{public:virtual void createdCar(void) = 0;virtual ~Car() {}
};class BenzCar : public Car //奔驰车
{public:BenzCar(){cout << "Benz::Benz()" << endl;}virtual void createdCar(void){cout << "BenzCar::createdCar()" << endl;}~BenzCar(){cout << "BenzCar::DestroyCar" << std::endl;}
};class BmwCar : public Car //宝马车
{public:BmwCar(){cout << "Bmw::Bmw()" << endl;}virtual void createdCar(void){cout << "BmwCar::createdCar()" << endl;}~BmwCar(){cout << "BmwCar::DestroyCar" << std::endl;}
};class CarFactory //车厂
{public:Car* createSpecificCar(CarType type){switch (type){case BENZ://生产奔驰车return (new BenzCar());break;case BMW://生辰宝马车return (new BmwCar());break;default:return NULL;break;}}
};int main(int argc, char** argv)
{CarFactory carfac;Car* specificCarA = carfac.createSpecificCar(BENZ);//看到网上众多示例在new后没有delete,感觉不是特别严谨Car* specificCarB = carfac.createSpecificCar(BMW);delete specificCarA;delete specificCarB;return 0;
}
  1. 工厂方法模式
     工厂方法模式:不再只由一个工厂类决定那一个产品类应当被实例化,这个决定权被交给子类去做。当有新的产品(新型汽车)产生时,只要按照抽象产品角色、抽象工厂角色提供的方法来生成即可(新车型可以用一个新类继承创建产品即可),那么就可以被客户使用,而不必去修改任何已有的代 码。可以看出工厂角色的结构也是符合开闭原则。如下面UML类图:
     
    代码示例:
#include <iostream>
using namespace std;class Car//车类
{public:virtual void createdCar(void) = 0;virtual ~Car() {}
};class BenzCar : public Car //奔驰车
{public:BenzCar(){cout << "Benz::Benz()" << endl;}virtual void createdCar(void){cout << "BenzCar::createdCar()" << endl;}~BenzCar(){cout << "BenzCar::DestroyCar()" << endl;}
};class BmwCar : public Car //宝马车
{public:BmwCar(){cout << "Bmw::Bmw()" << endl;}virtual void createdCar(void){cout << "BmwCar::createdCar()" << endl;}~BmwCar(){cout << "BmwCar::DestroyCar()" << endl;}
};class Factory//车厂
{public:virtual Car* createSpecificCar(void) = 0;virtual ~Factory() {}
};class BenzFactory : public Factory//奔驰车厂
{public:virtual Car* createSpecificCar(void){return (new BenzCar());}~BenzFactory() { cout << "BenzFactory"; }
};class BmwFactory : public Factory//宝马车厂
{public:virtual Car* createSpecificCar(void){return (new BmwCar());}~BmwFactory() { cout << "BmwFactory"; }
};int main(int argc, char** argv)
{shared_ptr<Factory> factoryBenz(new BenzFactory());Car* specificCarA = factoryBenz->createSpecificCar();shared_ptr<Factory> factoryBmw(new BmwFactory());Car* specificCarB = factoryBmw->createSpecificCar();delete specificCarA;specificCarA = nullptr;delete specificCarB;specificCarB = nullptr;return 0;
}

3.抽象工厂类
在上面的工厂方法模式基础上,有需要生产高配版的奔驰和宝马,那工厂方法模式就有点鞭长莫及了,这就又有抽象工厂模式,UML类图如下:

代码如下:

#include <iostream>
using namespace std;
class Car//车类
{public:virtual void createdCar(void) = 0;virtual ~Car() {}
};class BenzCar : public Car //奔驰车
{public:BenzCar(){cout << "Benz::Benz()" << endl;}virtual void createdCar(void){cout << "BenzCar::createdCar()" << endl;}~BenzCar(){}
};class BmwCar : public Car //宝马车
{public:BmwCar(){cout << "Bmw::Bmw()" << endl;}virtual void createdCar(void){cout << "BmwCar::createdCar()" << endl;}~BmwCar() {}
};class HighCar //高配版车型
{public:virtual void createdCar(void) = 0;virtual ~HighCar() {}
};class HighBenzCar : public HighCar //高配奔驰车
{public:HighBenzCar(){cout << "HighBenzCarBenz::Benz()" << endl;}virtual void createdCar(void){cout << "HighBenzCar::createdCar()" << endl;}~HighBenzCar() {}
};class HighBmwCar : public HighCar //高配宝马车
{public:HighBmwCar(){cout << "HighBmwCar::Bmw()" << endl;}virtual void createdCar(void){cout << "HighBmwCar::createdCar()" << endl;}~HighBmwCar() {}
};class Factory//车厂
{public:virtual Car* createSpecificCar(void) = 0;virtual HighCar* createdSpecificHighCar(void) = 0;virtual ~Factory() {}
};class BenzFactory : public Factory//奔驰车厂
{public:virtual Car* createSpecificCar(void){return (new BenzCar());}virtual HighCar* createdSpecificHighCar(void){return (new HighBenzCar());}~BenzFactory() {}
};class BmwFactory : public Factory//宝马车厂
{public:virtual Car* createSpecificCar(void){return (new BmwCar());}virtual HighCar* createdSpecificHighCar(void){return (new HighBmwCar());}~BmwFactory() {}
};int main(int argc, char** argv)
{Factory* factory = new BenzFactory();Car* specificCar = factory->createSpecificCar();HighCar* spcificHighCar = factory->createdSpecificHighCar();delete factory; delete specificCar; delete spcificHighCar;return 0;
}

C++之23种经典设计模式(一)相关推荐

  1. 23种经典设计模式都有哪些,如何分类?Java设计模式相关面试

    23种经典设计模式都有哪些,如何分类? 23种经典设计模式都有哪些,如何分类? java常用的设计模式?说明工厂模式 Java 中的23 种设计模式: Factory(工厂模式), Builder(建 ...

  2. 设计模式之委派模式(不属于23种经典设计模式之一)

    介绍 标准定义:委派模式的原理为类B和类A是两个互相没有任何关系的类,B具有和A一模一样的方法和属性,并且调用B中的方法.属性就是调用A中同名的方法和属性.B好像就是一个受A授权委托的中介.第三方的代 ...

  3. 23种经典设计模式的原理、背后的思想、应用场景(下)

    对程序员来说,除了算法,设计模式也是提升代码能力的关键技能,今天我就想跟你聊聊 23种经典的设计模式. 23种经典设计模式共分为3种类型,分别是创建型.结构型和行为型.今天,我们把这3种类型分成3个对 ...

  4. [设计模式] GoF 23种经典设计模式

    原文链接:https://www.yuque.com/cppdev/patterns/zainii 「GOF设计模式」Gang of Four,四人帮.设计模式的经典书籍<设计模式--可复用面向 ...

  5. 一文快速理解23种经典设计模式

    > 对经典的23种设计模式介绍,来判断适合哪种设计模式进行设计 23种设计模式: 第1 部分 适应设计模式   Iterator 模式 迭代器,松耦合 Adapter 模式 适配器模式,使用同样 ...

  6. 在这里23种经典设计模式UML类图汇总

    创建型模式 1.FACTORY-追MM少不了请吃饭了,麦当劳的鸡翅和肯德基的鸡翅都是MM爱吃的东西,虽然口味有所不同,但不管你带MM去麦当劳或肯德基,只管向服务员说"来四个鸡翅"就 ...

  7. 14. 23种经典设计模式-27-装饰者模式

    1. 装饰模式(Decorator Pattern) Attach additional responsibilities to an object dynamically keeping the s ...

  8. [转]23种经典设计模式的java实现_5_职责链模式

    对于职责链模式,一般是这么定义的:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,即--将这些对象连成一条(处理)链,并沿着这条链传递该请求,直到这条链结束同时有一个对象处理它 ...

  9. 23种经典设计模式的java实现_5_职责链模式

    对于职责链模式,一般是这么定义的:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,即--将这些对象连成一条(处理)链,并沿着这条链传递该请求,直到这条链结束同时有一个对象处理它 ...

最新文章

  1. 麻省理工学院计算机博士年薪,麻省理工学院计算机博士录取要求
  2. console用法java_使用console对javaScirpt进行全面调试-全面分析console用法
  3. 人工智能和中国学霸比赛做卷子居然输了?
  4. SpringSecurity - 基础篇
  5. 05.full_text match_bool_prefix match_phrase_prefix 查询
  6. Service Mesh服务网格:是什么和为什么
  7. labelimg如何调整框的颜色_P图改字:来看看吧!教你如何用PS墙壁发光灯泡广告文字图片...
  8. jQuery最简单的留言功能^-^
  9. 云图说|华为HiLens云上管理平台 花样管理多种端侧设备
  10. 画一画javascript原型链
  11. Android点赞头像列表
  12. 力扣-61 旋转链表
  13. iOS The binary you uploaded was invalid
  14. 2021-2027全球与中国数控龙门镗铣床市场现状及未来发展趋势
  15. Workflow 规则大全 最新版
  16. 苏州大学计算机考研 复试机试真题2013-2020真题及Python题解
  17. 鸿蒙可能超越安卓吗,华为鸿蒙能超越安卓吗?或一统江湖?任正非已志在必得...
  18. 程序员的算法趣题Q09: 落单的男女
  19. 最强前端笔记(没有之一)(^-^)
  20. 6-1 Numerical Summation of a Series (40分)

热门文章

  1. 基于 CNN-GRU 的菇房多点温湿度预测方法研究 学习记录
  2. 汉邦高科参与华为鸿蒙系统,汉邦高科(300449)06月27日10:30大单揭秘
  3. WPF字体模糊解决方案
  4. 测试dali协议的软件,如何使用示波器分析DALI协议?
  5. 数据分析之前程无忧(一)
  6. 聊一聊Asp.net过滤器Filter那一些事
  7. Windows命令操作
  8. 算法 — 杨辉三角形
  9. python字符串怎么计算_Python字符串相似性的几种计算方法
  10. draft伦理第四章