单例模式是一种对象创建型的设计模式,使用单例模式,可以保证一个类只生成唯一的实例对象。也就是说,在整个程序中,该类只存在一个实例对象。
单例模式实现步骤-
构造函数私有化
-
提供一个全局的静态方法,访问唯一的对象
-
类中定义一个静态的指针,指向唯一的对象
类图如下,两个公有属性,然后把构造函数私有化就可以了
为什么使用单例模式?在应用系统开发过程中,如果有以下四个需求通常都可以采用单例模式:
1.需要生成唯一序列的环境
2.需要频繁实例化然后销毁的对象
3.创建对象时耗时过多或者消耗资源过多,但又经常用到的对象
4.方便资源相互通信的环境
实际案例:
-
多线程中网络资源初始化(网络资源共享,可以采用单例设计模式的方式去设计)
-
回收站机制
-
任务管理器(如果怎么打开任务管理器 / 回收站,永远都只会出现一个窗口)
-
应用程序日志管理(保证读写方式能够每次都进行一个追加模式去做一个日志操作)
-
... ...
懒汉式:直接在静态方法中构造对象,不在外面创建对象
#includeusing namespace std; class SingleTon { public: static SingleTon* m_singleTon; //提供一个静态指针 static SingleTon* GetInstance() //添加一个静态属性的方法给类外做访问 { if (m_singleTon == NULL) //首先判断对象是否存在 如果不存在就创建 { m_singleTon = new SingleTon; //对象在函数中创建 } return m_singleTon; //如果对象存在就没必要创建 直接返回就可以了 } void TestPrint() { cout << "测试调用....." << endl; } private: SingleTon() //构造函数私有化,类外无法创建对象 { cout << "构造对象......" << endl; m_singleTon = NULL; //给静态指针做初始化 } }; SingleTon* SingleTon::m_singleTon = NULL; //静态方法在类外初始化 使用类名限定 在类外不创建对象 int main() { //构造函数私有化 类外不能创建对象 但是可以创建指针 通过类名限定调用 SingleTon* p1 = SingleTon::GetInstance(); //两个指针指向同一个对象 SingleTon* p2 = SingleTon::GetInstance(); //用 16 进制打印 p1 和 p2 的地址 指向的是同一个对象 cout << "p1:" << hex << p1 << endl; cout << "p2:" << hex << p2 << endl; p1->TestPrint(); p2->TestPrint(); return 0; } 构造对象...... p1:000001E1FCBCD050 p2:000001E1FCBCD050 测试调用..... 测试调用.....
饿汉式:在外面直接构造对象,<不在静态方法中构造对象,直接返回>
由于饿汉式得方式是全局变量,在多线程当中可能会产生资源竞争的问题,需要自己做资源的调整或者加锁的过程
#include单例模式优缺点using namespace std; class SingleTon { public: static SingleTon* m_singleTon; //静态指针 static SingleTon* GetInstance() //提供静态方法 { //if (m_singleTon == NULL) //{ // m_singleTon = new SingleTon; //} return m_singleTon; } void TestPrint() { cout << "测试调用....." << endl; } private: SingleTon() //构造函数私有化 { cout << "构造对象......" << endl; m_singleTon = NULL; } }; //用对象指针直接 new 一个对象 无论是否使用 反正对象都是存在的 SingleTon* SingleTon::m_singleTon = new SingleTon; int main() { SingleTon* p1 = SingleTon::GetInstance(); SingleTon* p2 = SingleTon::GetInstance(); cout << "p1:" << hex << p1 << endl; cout << "p2:" << hex << p2 << endl; //简单调用 p1->TestPrint(); p2->TestPrint(); return 0; }
优点
-
在内存当中只有一个对象,节省内存空间
-
避免频繁地创建销毁对象,可以提高性能
-
避免对共享资源的多重占用,简化访问
-
为整个系统提供一个全局访问点
做游戏的过程中可以使用单例设计模式对资源进行把控,所有的资源用一个类去描述,所有的模块当中如果需要用到资源,就用同一个对象的属性
缺点
-
不适用于变化频繁的对象 / 经常做拷贝操作的对象
-
如果实例化的对象长时间未使用,系统会认为该对象是垃圾而被回收,这可能会导致对象状态的丢失
简单工厂模式属于类的创建型的设计模式,又叫做静态工厂方法模式。
通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
为什么使用简单工厂减少客户程序对类创建过程的依赖
简单工厂实现步骤1.提供一个工厂类:负责实现创建所有实例的内部逻辑。可被外界直接调用,创建所需的产品对象。
2.提供一个抽象产品类:简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口,所有产品公共的父类。
3.提供一个具体产品类:简单工厂模式所创建的具体实例对象,产品是怎么实现的?继承抽象类去实现产品
类图如下,实际产品继承抽象产品类
简单工厂实现代码如果自己去实现加减乘除,自己写类的话,可能很多人比如我可能直接就写在一个类里面了,如果用简单工厂的设计模式去实现去写的话,就需要去设计这么多类的实现
如果要有其他的运算符例如 %,还是需要去修改原来的工厂类代码,这是简单工厂模式的弊端,不适合我们去做拓展,违背了开放封闭原则
c++纯虚函数(特殊的虚函数)和ADT过程(抽象数据类型)_小雪菜本菜的博客-CSDN博客
#include简单工厂优缺点using namespace std; //抽象一个产品类 class Operation { public: //这里采用产品的公有属性<一般写私有属性减少与类外的联系> //左值 double m_leftValue; //右值 double m_rightValue; //由于是抽象类 提供一个纯虚函数 virtual double GetResult() = 0; }; //具体产品继承抽象产品类 //加 产品 1 class AddOperation :public Operation { double GetResult() { //左值加右值 return m_leftValue + m_rightValue; } }; //减 产品 2 class SubOperation :public Operation { double GetResult() { return m_leftValue - m_rightValue; } }; //乘 产品 3 class MulOperation :public Operation { double GetResult() { return m_leftValue * m_rightValue; } }; //除 产品 4 class DivOperation :public Operation { double GetResult() { //暂时不考虑除数为 0 的情况 return m_leftValue / m_rightValue; } }; //工厂类负责整个产品的创建 class OperatorFatory { public: //用静态方法判定需要什么产品 返回产品的父类指针用字符表示运算符的类型 用子类对象初始化父类指针 static Operation* createOperation(char c) { //针对运算符做不同的对象创建 switch (c) { case '+': //返回加法的对象 return new AddOperation; break; case '-': //... return new SubOperation; break; case '*': return new MulOperation; break; case '/': return new DivOperation; break; } return NULL; } }; int main() { //传入加法创建加法的产品 通过 OperatorFatory 工厂来创建一个对象 Operation* add = OperatorFatory::createOperation('+'); //初始化左值和右值 add->m_leftValue = 1; add->m_rightValue = 2; //打印结果 cout << add->GetResult() << endl; //如果需要不同的产品就创建不同的对象 接下来创建一个减法 add = OperatorFatory::createOperation('-'); //一般情况会把数据放在构造函数中初始化 每次产品创建好后都要做初始化 add->m_leftValue = 3; add->m_rightValue = 4; cout << add->GetResult() << endl; return 0; } 3 -1
优点
-
帮助封装
实现组件封装,面向(工厂类的接口)接口编程
-
解耦合
客户端和具体实现类的解耦合(继承产品类是解耦合的一个过程,把抽象产品类和具体产品做了一个分离过程,类似依赖倒置原则)
缺点
-
可能增加客户端的复杂度
-
不方便扩展子工厂(如果有新的工程,要修改原代码并且实现新的类)



