c++ 设计模式 --- 单例模式、简单工厂

什么是单例模式

单例模式是一种对象创建型的设计模式,使用单例模式,可以保证一个类只生成唯一的实例对象。也就是说,在整个程序中,该类只存在一个实例对象。

单例模式实现步骤

  1. 构造函数私有化

  2. 提供一个全局的静态方法,访问唯一的对象

  3. 类中定义一个静态的指针,指向唯一的对象

类图如下,两个公有属性,然后把构造函数私有化就可以了

c++ 设计模式 --- 单例模式、简单工厂_第1张图片

为什么使用单例模式?

在应用系统开发过程中,如果有以下四个需求通常都可以采用单例模式:

1.需要生成唯一序列的环境

2.需要频繁实例化然后销毁的对象

3.创建对象时耗时过多或者消耗资源过多,但又经常用到的对象

4.方便资源相互通信的环境

实际案例:

  • 多线程中网络资源初始化(网络资源共享,可以采用单例设计模式的方式去设计)

  • 回收站机制

  • 任务管理器(如果怎么打开任务管理器 / 回收站,永远都只会出现一个窗口)

  • 应用程序日志管理(保证读写方式能够每次都进行一个追加模式去做一个日志操作)

  • ... ...

单例模式实现代码

懒汉式:直接在静态方法中构造对象,不在外面创建对象

#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;                 //给静态指针做初始化
    }
};
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++ 设计模式 --- 单例模式、简单工厂_第2张图片

简单工厂实现代码

如果自己去实现加减乘除,自己写类的话,可能很多人比如我可能直接就写在一个类里面了,如果用简单工厂的设计模式去实现去写的话,就需要去设计这么多类的实现

如果要有其他的运算符例如 %,还是需要去修改原来的工厂类代码,这是简单工厂模式的弊端,不适合我们去做拓展,违背了开放封闭原则

c++纯虚函数(特殊的虚函数)和ADT过程(抽象数据类型)_小雪菜本菜的博客-CSDN博客

#include 
using namespace std;
/*
    简单计算器: + - * /
    1.提供一个工厂类:     提供运算方式 产生不同产品      
    2.提供一个抽象产品类: 运算符类 + 提供接口负责运算得到结果
    3.提供一个具体产品类: 具体运算符类:加法类、减法类、乘法类、除法类...
*/
​
//抽象一个产品类
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;
        }
        /*  warning C4715: “OperatorFatory::createOperation”: 不是所有的控件路径都返回值 */
        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

简单工厂优缺点

优点

  • 帮助封装

    实现组件封装,面向(工厂类的接口)接口编程

  • 解耦合

    客户端和具体实现类的解耦合(继承产品类是解耦合的一个过程,把抽象产品类和具体产品做了一个分离过程,类似依赖倒置原则)

缺点

  • 可能增加客户端的复杂度

  • 不方便扩展子工厂(如果有新的工程,要修改原代码并且实现新的类)

你可能感兴趣的:(设计模式,c++,设计模式,单例模式,简单工厂)