C++闲谈04——设计模式

news2024/9/21 17:55:02

C++闲谈04——设计模式

单例模式

饿汉式单例模式

#include<iostream>
#include<mutex>

using namespace std;
mutex mtx;


class SingleTon{
public:
    static SingleTon* GetInstance() {
        if (instance == nullptr) {
            lock_guard<mutex> lk(mtx);  // 不是尖括号
            instance = new SingleTon();
        }

        return instance;
    }
private:
    SingleTon() {
        cout << "test" << endl;
    }

    static SingleTon* instance;
};

SingleTon* SingleTon::instance = nullptr;

int main() {
    SingleTon* test1 = SingleTon::GetInstance();
    SingleTon* test2 = SingleTon::GetInstance();
    system("pause");
    return 0;
}

优点:对象提前创建好了 使用的时候无需等待

缺点:对象提前创建 占用内存

懒汉式单例模式

#include<iostream>
#include<mutex>

using namespace std;
mutex mtx;


class SingleTon{
public:
    static SingleTon* GetInstance() {
        if (instance == nullptr) {
            lock_guard<mutex> lk(mtx);  // 不是尖括号
            instance = new SingleTon();
        }

        return instance;
    }
private:
    SingleTon() {
        cout << "test" << endl;
    }

    static SingleTon* instance;
};

SingleTon* SingleTon::instance = nullptr;

int main() {
    SingleTon* test1 = SingleTon::GetInstance();
    SingleTon* test2 = SingleTon::GetInstance();
    system("pause");
    return 0;
}

优点:使用的时候才创建 不占内存

缺点:使用的时候需要创建 比较耗时

工厂模式

工厂模式

简单工厂模式

  • 工厂类
  • 抽象产品类
  • 具体产品类

image-20221203120811174

#include <iostream>
#include <vector>
using namespace std;
  
typedef enum ProductTypeTag
{
  Hair,
  Hisense,
}PRODUCTTYPE;
  
//抽象产品类 TV(电视机类)
class TV
{
public:
  virtual void Show() = 0;
  virtual ~TV(){};//声明析构函数为虚函数,防止内存泄漏
};
 //具体产品类 HairTV(海尔电视类)
class HairTV : public TV
{
public:
  void Show()
  {
    cout<<"I'm HairTV "<<endl;
  }
};
 //具体产品类 HisenseTV(海信电视类)  
class  HisenseTV : public TV
{
public:
  void Show()
  {
    cout<<"I'm HisenseTV"<<endl;
  }
};
  
 
// 工厂类 TVFactory(电视机工厂类)
class TVFactory
{
public:
  TV* CreateTV(PRODUCTTYPE type)
  {
    switch (type)
    {
    case Hair:
      return new HairTV();
  
    case Hisense:
      return new HisenseTV();
    default:
      return NULL;
    }
  }
};
  
int main(int argc, char *argv[])
{
    // 创建工厂类对象
    TVFactory* myTVFactory = new  TVFactory();
    TV* hairTV = myTVFactory->CreateTV(Hair);
    if (hairTV != NULL)
        hairTV->Show();
 
    TV* hisenseTV = myTVFactory->CreateTV(Hisense);
    if (hisenseTV != NULL)
        hisenseTV->Show();
 
    delete  myTVFactory;
    myTVFactory = NULL;
 
    delete hairTV;
    hairTV = NULL;
 
    delete hisenseTV;
    hisenseTV = NULL;  
  
    return 0;
}

TVFactory 是工厂类,它是整个系统的核心,提供了静态工厂方法CreateTV(),该方法中包含一个字符串类型的参数,在内部业务逻辑中根据参数值得不同实例化不同的具体产品类,返回相依的对象。简单工厂模式的缺点是 如增加 生成TCL电视时,需要修改工厂类TVFactory。

小结:

在程序中,需要创建的对象很多,导致对象的new操作多且杂时,需要使用简单工厂模式。

工厂方法模式

简单工厂模式中最大的缺点是当有新产品要加入系统时,必须要修改工厂类,加入必要的处理逻辑,违背了“开闭原则”

工厂方法模式定义:在工厂模式中,工厂父类负责定义创建产品对象的公告接口,而工厂子类负责生成具体的产品对象。目的是将产品的实例化操作延迟到工厂子类中完成,通过工厂子类来确定究竟应该实例化哪一个具体产品类。

image-20221203145257797

工厂方法模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。

#include <iostream>
using namespace std;
 /*抽象产品类 TV(电视机类)*/ 
class TV
{
public:
  virtual void Show() = 0;
 virtual ~TV();//声明析构函数为虚函数,防止内存泄漏
};
 /*具体产品类 HairTV(海尔电视机类)*/ 
class HairTV : public TV
{
public:
  void Show()
  {
    cout<< "I'm HairTV"<<endl;
  }
};
/*具体产品类 HisenseTV(海信电视机类)*/
class HisenseTV : public TV
{
public:
  void Show()
  {
    cout<< "I'm HisenseTV"<<endl;
  }
};
/*工厂类(电视机工厂类)*/  
class TVFactory
{
public:
  virtual TV *CreateTV() = 0;
   virtual ~TVFactory(){};//析构函数声明为虚函数,防止内存泄漏
};
 /*具体工厂类 HairTVFactory(海尔电视机工厂类)*/ 
class HairTVFactory : public TVFactory
{
public:
  TV *CreateTV()
  {
    return new HairTV ();
  }
};
 /*具体工厂类 HisenseTV(海信电视机工厂类)*/ 
class HisenseTVFactory : public TVFactory
{
public:
  TV *CreateTV()
  {
    return new HisenseTV ();
  }
};
  
int main(int argc , char *argv [])
{
  TVFactory *hairTVFactory = new HairTVFactory();
  TV *hairTV = hairTVFactory->CreateTV();
  hairTV->Show();
  
  TVFactory *hisenseTVFactory = new HisenseTVFactory();
  TV *hisenseTV = hisenseTVFactory->CreateTV();
  hisenseTV->Show();
  
  if (hairTVFactory!= NULL)
  {
    delete hairTVFactory;
    hairTVFactory = NULL;
  }
  
  if (hairTV != NULL)
  {
    delete hairTV;
    hairTV = NULL;
  }
  
  if (hisenseTVFactory != NULL)
  {
    delete hisenseTVFactory;
    hisenseTVFactory = NULL;
  }
  
  if (hisenseTV != NULL)
  {
    delete hisenseTV;
    hisenseTV = NULL;
  }
  return 0;
}

抽象工厂模式

抽象工厂模式是工厂方法模式的泛化版,工厂模式是一种特殊的抽象工厂模式,在工厂模式中,每个具体工厂只能生产一种具体的产品,如海尔电视机厂只生产海尔电视机,而抽象工厂方法模式中,一个具体的工厂可以生产多个具体产品。

image-20221203145524563

优点:

抽象工厂模式将产品族的依赖与约束关系放到抽象工厂中,便于管理。
职责解耦,用户不需要关心一堆自己不关心的细节,由抽象工厂来负责组件的创建
切换产品族容易,只需要增加一个具体工厂实现,客户端选择另一个套餐就可以了
缺点:

抽象工厂模式类增加的速度很快,有一个产品族就需要增加一个具体工厂实现,比较繁琐
产品族难以扩展产品。当产品族中增加一个产品时,抽象工厂接口中需要增加一个函数,对应的所有具体工厂实现都需要修改,修改放大严重。
抽象工厂并未完全屏蔽创建细节,给出的都是组件。对于这种情况可以结合工厂模式或简单工厂模式一起使用

#include <iostream>
using namespace std;
  
// 抽象产品类类 Television(电视机类)
class Television
{
public:
    virtual void Show() = 0;
    virtual ~Television(){};//析构函数声明为虚函数,防止内存泄漏
};
 
//具体产品类 HaierTelevision(海尔电视机类)
class HaierTelevision : public Television
{
public:
    void Show()
    {
        cout << "I'm HaierTelevision" << endl;
    }
};
//具体产品类 TCLTelevision(TCL电视机类)
class TCLTelevision : public Television
{
public:
    void Show()
    {
        cout << "I'm TCLTelevision" << endl;
    }
};
 
// 抽象产品类  AirCondition(空调类)
class AirCondition
{
public:
    virtual void Show() = 0;
    virtual ~AirCondition(){};//析构函数声明为虚函数,防止内存泄漏
};
//具体产品类 HairAirCondition(海尔空调类)
class HairAirCondition : public AirCondition
{
public:
    void Show()
    {
        cout << "I'm HairAirCondition" << endl;
    }
};
//具体产品类 TCLAirCondition(TCL空调类)
class TCLAirCondition : public AirCondition
{
public:
    void Show()
    {
        cout << "I'm TCLAirCondition" << endl;
    }
};
 
// 抽象工厂类 EFactory(电器工厂类)
class EFactory
{
public:
    virtual Television* CreateTelevision() = 0;
    virtual AirCondition* CreateAirCondition() = 0;
     virtual ~EFactory(){};//析构函数声明为虚函数,防止内存泄漏
};
//具体工厂类 HairFactory(海尔工厂类)
class HairFactory : public EFactory
{
public:
    Television* CreateTelevision()
    {
        return new HaierTelevision();
    }
 
    AirCondition* CreateAirCondition()
    {
        return new HairAirCondition();
    }
};
//具体工厂类 TCLFactory(TCL工厂类) 
class TCLFactory : public EFactory
{
public:
    Television* CreateTelevision()
    {
        return new TCLTelevision();
    }
 
    AirCondition* CreateAirCondition()
    {
        return new TCLAirCondition();
    }
};
  
int main(int argc, char *argv[])
{
  EFactory *hairFactory = new HairFactory ();/*实例化工厂抽象类*/
  Television *haierTelevision =hairFactory->CreateTelevision();/*实例化产品抽象类*/
  AirCondition *haierAirCondition = hairFactory->CreateAirCondition();
  
  haierTelevision->Show();
  haierAirCondition->Show();
  
  EFactory *tCLFactory = new TCLFactory ();
  Television *tCLTelevision = tCLFactory->CreateTelevision();
  AirCondition *tCLAirCondition = tCLFactory->CreateAirCondition();
  
  tCLTelevision->Show();
  tCLAirCondition->Show();
  
  if (hairFactory != NULL)
  {
    delete hairFactory;
    hairFactory = NULL;
  }
  
  if (haierTelevision != NULL)
  {
    delete haierTelevision;
    haierTelevision= NULL;
  }
  
  if (tCLAirCondition != NULL)
  {
    delete tCLAirCondition;
    tCLAirCondition = NULL;
  }
  
  if (tCLFactory != NULL)
  {
    delete tCLFactory;
    tCLFactory= NULL;
  }
  
  if (tCLTelevision != NULL)
  {
    delete tCLTelevision;
    tCLTelevision = NULL;
  }
  
  if (tCLAirCondition != NULL)
  {
    delete tCLAirCondition;
    tCLAirCondition = NULL;
  }
}

总结

大家应该已经发现了,其实抽象工厂模式如果只有一个组件的话,其实是退化到了工厂方法模式,也就是没有了产品族的概念,只剩一个产品了,因此简单工厂,工厂方法,抽象工厂这三者之间是有内在联系的,区别只是产品的复杂度。

抽象工厂的本质是选择产品族,因此大家可以根据这个特征来识别是否可以应用抽象工厂。
简单工厂:唯一工厂类,一个产品抽象类,工厂类的创建方法依据入参判断并创建具体产品对象。
工厂方法:多个工厂类,一个产品抽象类,利用多态创建不同的产品对象,避免了大量的if-else判断。
抽象工厂:多个工厂类,多个产品抽象类,产品子类分组,同一个工厂实现类创建同组中的不同产品,减少了工厂子类的数量。 增加了泛化能力

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/60217.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

修复 爱普生 EPSON L4156 打印机 无法打印,开关 WIFI 墨水 三个灯同时闪烁的问题

L4151 L4153 L4156 L4158 L4163 L4165 L4166 L4168 L4169 喷墨一体机清零图解 清零前请取消打印任务&#xff0c;打印机用 USB 线接电脑并开启 工具下载地址 EPSON打印机清零软件1.双击[Resetter.exe]启动软件,点击[Select],选择 Port 打 印机型号&#xff0c;然后点[OK]&#…

第8章 注意力机制与外部记忆

系列文章目录 第1章 绪论 第2章 机器学习概述 第3章 线性模型 第4章 前馈神经网络 第5章 卷积神经网络 第6章 循环神经网络 第7章 网络优化与正则化 第8章 注意力机制与外部记忆 第9章 无监督学习 第10章 模型独立的学习方式 第11章 概率图模型 第12章 深度信念网络 第13章 深…

Linux UART编程 驱动蓝牙芯片

在熟悉了UART概念后&#xff0c;我们要学以致用&#xff0c;在Linux用起来来驱动起来蓝牙芯片&#xff01; 我们直接借用man来看下&#xff0c;命令如下&#xff1a; man termios 1.头文件引用 #include <termios.h> #include <unistd.h> 2.串口打开关闭 open…

Python预测2022世界杯1/8决赛胜负

目录: why to do?how to do?why to do? 简单介绍一下为什么要做这个吧? 首先呢, 最近一直在看基于tensorflow框架实现facenet等一些人脸识别的网络. 再加上昨天(2022年12月3日)是2022年世界杯1/8决赛第一个比赛日. 就在不同平台搜了一下, 看看有没有其他大牛也做了这方面的…

设计模式——策略模式

设计模式中的复用性指的是编译单位&#xff08;二进制层面&#xff09;的复用性&#xff08;编译、测试、部署后是原封不动的&#xff09; 动机&#xff08;Motivation&#xff09; 在软件构建过程中&#xff0c;某些对象使用的算法可能多种多样&#xff0c;经常改变&#xf…

Netty系列(五):源码解读ServerBootstrapAcceptor类职能,探究Netty启动流程

ServerBootstrapAcceptor是Netty服务端用来接收客户端连接的核心类&#xff0c;本文将介绍ServerBootstrapAcceptor的职能。 init方法 在上一篇文章源码解读 backlog 参数作用中我们知道&#xff0c;在Netty服务端启动时&#xff0c;会调用ServerBootstrap.bind()绑定本地端口…

玩转GDAL一文带你深入Windows下FileGDB驱动支持

前言 了解GDAL的朋友一定知道&#xff0c;GDAL3.5以下&#xff08;含&#xff09;默认配置下是只支持gdb文件的读的&#xff0c;是不支持写的。更要命的是&#xff0c;默认的OpenFileGDB在读取时&#xff0c;如果我们在矢量文件中设置了属性表字段的别名&#xff0c;默认驱动是…

Git项目演练

Git项目演练 首先&#xff0c;进入到项目路径 然后&#xff0c;初始化&#xff0c;产生.git库 创建gitignore文件 将不需要的文件放入到,gitignore 将所有的文件添加到追踪的状态 对文件进行一次提交 使用git log查看变动 使用编译器修改代码中的内容 对修改进…

基于javaweb的学籍管理系统计算机毕业论文java毕业设计选题源代码

&#x1f496;&#x1f496;更多项目资源&#xff0c;最下方联系我们✨✨✨✨✨✨ 目录 Java项目介绍 资料获取 Java项目介绍 计算机毕业设计java毕设之基于javaweb的学籍管理系统-IT实战营_哔哩哔哩_bilibili项目资料网址: http://itzygogogo.com软件下载地址:http://itzy…

【能效管理】安科瑞新能源充电桩收费运维管理云平台应用分析

概述 AcrelCloud-9000安科瑞充电桩收费运营云平台系统通过物联网技术对接入系统的汽车充电站、电动自行车充电站以及各个充电桩进行不间断地数据采集和监控&#xff0c;实时监控充电桩运行状态&#xff0c;进行充电服务、支付管理&#xff0c;交易结算&#xff0c;资源管理、电…

ADSP-21569/ADSP-21593的开发入门(上)

作者的话 ADI的SHARC系列DSP&#xff0c;目前已经出到5系列了&#xff0c;最新的一颗叫2159x&#xff0c;按照ADI的说法&#xff0c;这颗DSP的性能是21569的两倍&#xff0c;但又能和21569做P2P的替换&#xff0c;所以下面我们就以21593为例&#xff0c;写一点资料&#xff0c…

头歌计算机组成原理MIPS RAM设计

完整答案点击底部 <?xml version"1.0" encoding"UTF-8" standalone"no"?> <project source"2.15.0.2.exe" version"1.0"> This file is intended to be loaded by Logisim http://logisim.altervista.org &l…

数字化门店| 旧衣回收店系统 | 智慧门店小程序开发教程

随着人们生活质量的提升&#xff0c;无论男女&#xff0c;衣柜鞋柜里摆满了各种衣物&#xff0c;覆盖了多个场景下的衣物非常多&#xff0c;同时如今大多数人已经不再穿补丁衣服&#xff0c;旧或破就会扔掉买新的。为了节省资源及合理二次利用&#xff0c;旧衣回收行业逐渐出现…

用译码器来设计组合逻辑电路

三线到八线&#xff1a;输入端只有三个所以只能是三变量 我们先来看书上的一个例子 设计的过程第一步 将函数表达式整理成最小项和的形式 我们用来举例&#xff0c;不是最小项的形式 三变量函数可以用三变量的最小项来表示 为了看的更清楚&#xff0c;我们写成最小项的编号&…

四、Git本地仓库基本操作——查看提交历史和版本回退前进

1. 查看提交历史 查看git提交历史一般常用两个命令&#xff1a; # 查看历史提交记录 git log # 以列表形式查看指定文件的历史记录 git blame <文件名>git log 该命令会按照我们提交的时间线&#xff0c;然后列出所有的历史提交。 示例&#xff1a; git log 显示的…

[附源码]计算机毕业设计JAVA医疗预约系统

[附源码]计算机毕业设计JAVA医疗预约系统 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis M…

【Pytorch】广播机制

【参考&#xff1a;The size of tensor a must match the size of tensor b (y) at non-singleton dimension z_点PY的博客-CSDN博客】 报错&#xff1a;The size of tensor a (x) must match the size of tensor b (y) at non-singleton dimension z 其广播机制遵循以下规则…

[附源码]计算机毕业设计基于springboot的连锁药店销售管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

mediasoup学习与实践

一、mediasoup基本概念&#xff1a; 基础架构 1、worker 2、router 3、producer 4、consumer 5、transport 整体结构 特性 1、支持IPv6 2、ICE/DRLS/RTP/RTCP over UDP and TCP 3、支持simulcast和svc 4、支持拥塞控制 5、带宽控制 6、支持&#xff1a;STCP 7、多流使用同一…

安全可靠的SRT实时传输协议

Secure Reliable Transport(SRT)是安全、可靠、低延时的多媒体实时传输协议。SRT协议使用AES进行数据加密&#xff0c;运用FEC进行前向纠错&#xff0c;并且有流量控制、拥塞控制。类似于QUIC协议&#xff0c;SRT采用UDP代替TCP&#xff0c;在应用层提供发送确认机制、ARQ自动重…