当前位置: 首页 > news >正文

c++设计模式之一创建型模式

1、创建型模式(常见的设计模式)

Factory 模式(工厂模式,被实例化的子类)

在面向对象系统设计中经常可以遇到以下的两类问题:

下面是第一类问题和代码示例:我们经常会抽象出一些类的公共接口以形成抽象基类或者接口。这样我们可以通过声明一个指向基类的指针来指向实际的子类实现,达到了多态的目的。所以就不得不在要用到子类的地方写new 对象。这样实体类的使用者必须知道实际的子类名称,以及会使程序的扩展性和维护变得越来越困难。

#include <iostream>// 抽象基类或接口
class Animal {
public:virtual void makeSound() = 0; // 纯虚函数
};// 具体子类
class Dog : public Animal {
public:void makeSound() override {std::cout << "Woof!" << std::endl;}
};class Cat : public Animal {
public:void makeSound() override {std::cout << "Meow!" << std::endl;}
};int main() {Animal* animal;// 通过指向基类的指针指向具体的子类实例animal = new Dog();animal->makeSound();animal = new Cat();animal->makeSound();return 0;
}

在上述示例中,我们定义了一个抽象基类 Animal,其中包含一个纯虚函数 makeSound()。然后我们派生出两个具体的子类 Dog 和 Cat,并分别实现了 makeSound() 方法。在 main() 函数中,我们使用指向基类的指针 animal,通过 new 实例化具体的子类,并调用其方法。这样可以实现多态性,但使用者需要知道具体的子类名称,不利于程序的扩展性和维护。 

还有一种情况就是在父类中并不知道具体要实例化哪一个具体的子类。只能在父类中写方法调用,具体调用哪一个类的方法交给子类实现

#include <iostream>// 抽象基类
class Animal {
public:virtual void makeSound() = 0; // 纯虚函数void performAction() {std::cout << "Performing action: ";makeSound();}
};// 具体子类
class Dog : public Animal {
public:void makeSound() override {std::cout << "Woof!" << std::endl;}
};class Cat : public Animal {
public:void makeSound() override {std::cout << "Meow!" << std::endl;}
};int main() {Animal* animal = nullptr;int choice;std::cout << "Enter 1 for Dog, 2 for Cat: ";std::cin >> choice;// 根据用户的选择实例化不同的子类if (choice == 1) {animal = new Dog();} else if (choice == 2) {animal = new Cat();} else {std::cout << "Invalid choice" << std::endl;return 0;}animal->performAction();delete animal;return 0;
}

在上述示例中,我们仍然有一个抽象基类 Animal,其中包含一个纯虚函数 makeSound()。不同之处在于,在 Animal 类中我们添加了一个 performAction() 方法,该方法调用了 makeSound() 方法。在 main() 函数中,根据用户的选择实例化不同的子类,并通过基类指针调用 performAction() 方法。这样,具体调用哪个子类的方法由子类自己实现,父类并不知道具体的子类实例化。

以上两个问题也就引出了 Factory 模式的两个最重要的功能:
1)定义创建对象的接口,封装了对象的创建。
2)使得具体化类的工作延迟到了子类中。

工厂模式代码示例

#include <iostream>
#include <string>// 抽象产品类
class Product {
public:virtual void use() const = 0;
};// 具体产品类 A
class ConcreteProductA : public Product {
public:void use() const override {std::cout << "Using ConcreteProductA" << std::endl;}
};// 具体产品类 B
class ConcreteProductB : public Product {
public:void use() const override {std::cout << "Using ConcreteProductB" << std::endl;}
};// 工厂类
class Factory {
public:virtual Product* createProduct() const = 0;Product* getProduct() const {Product* product = createProduct();// 可以在这里添加其他的初始化逻辑return product;}
};// 具体工厂类 A
class ConcreteFactoryA : public Factory {
public:Product* createProduct() const override {return new ConcreteProductA();}
};// 具体工厂类 B
class ConcreteFactoryB : public Factory {
public:Product* createProduct() const override {return new ConcreteProductB();}
};int main() {Factory* factory = nullptr;Product* product = nullptr;std::string choice;std::cout << "Enter A for ConcreteProductA, B for ConcreteProductB: ";std::cin >> choice;// 根据用户的选择实例化不同的具体工厂类if (choice == "A") {factory = new ConcreteFactoryA();} else if (choice == "B") {factory = new ConcreteFactoryB();} else {std::cout << "Invalid choice" << std::endl;return 0;}// 使用工厂类创建产品对象product = factory->getProduct();product->use();delete factory;delete product;return 0;
}

AbstactFactory 模式 (产品对象家族)

假如我们要买水果,水果的产地来自中国、日本、美国,每个国家的水果种类都可以分为苹果、香蕉、梨子。作为开发者,我们就不得不创建苹果类(香蕉和梨子类似),然后每种苹果都继承自苹果类。每上架一个国家的苹果我们都要实现一次苹果类,这样就会有成千上万的苹果类需要被创建,AbstractFactory 模式就是用来解决这类问题的:要创建一组相关或者相互依赖的对象。

//抽象工厂模式
#include <iostream>
using namespace std;//苹果的抽象
class AbstractApple {
public:virtual void showName() = 0;
};//中国苹果
class ChinaApple :public AbstractApple {
public:virtual void showName() {cout << "中国苹果" << endl;}
};//美国苹果
class USAApple :public AbstractApple {
public:virtual void showName() {cout << "美国苹果" << endl;}
};//日本苹果
class JapanApple :public AbstractApple {
public:virtual void showName() {cout << "日本苹果" << endl;}
};//香蕉的抽象
class AbstractBanana {
public:virtual void showName() = 0;
};//中国香蕉
class ChinaBanana :public AbstractBanana {
public:virtual void showName() {cout << "中国香蕉" << endl;}
};//美国香蕉
class USABanana :public AbstractBanana {
public:virtual void showName() {cout << "美国香蕉" << endl;}
};//日本香蕉
class JapanBanana :public AbstractBanana {
public:virtual void showName() {cout << "日本香蕉" << endl;}
};//鸭梨的抽象
class AbstractPear {
public:virtual void showName() = 0;
};//中国鸭梨
class ChinaPear :public AbstractPear {
public:virtual void showName() {cout << "中国鸭梨" << endl;}
};//美国鸭梨
class USAPear :public AbstractPear {
public:virtual void showName() {cout << "美国鸭梨" << endl;}
};//日本鸭梨
class JapanPear :public AbstractPear {
public:virtual void showName() {cout << "日本鸭梨" << endl;}
};//抽象工厂  针对产品族
class AbstractFactory {
public:virtual AbstractApple* CreateApple() = 0;virtual AbstractBanana* CreateBanana() = 0;virtual AbstractPear* CreatePear() = 0;
};//中国工厂
class ChinaFactory :public AbstractFactory {virtual AbstractApple* CreateApple() {return new ChinaApple;}virtual AbstractBanana* CreateBanana() {return new ChinaBanana;}virtual AbstractPear* CreatePear() {return new ChinaPear;}
};//美国工厂
class USAFactory :public AbstractFactory {virtual AbstractApple* CreateApple() {return new USAApple;}virtual AbstractBanana* CreateBanana() {return new USABanana;}virtual AbstractPear* CreatePear() {return new USAPear;}
};//日本工厂
class JapanFactory :public AbstractFactory {virtual AbstractApple* CreateApple() {return new JapanApple;}virtual AbstractBanana* CreateBanana() {return new JapanBanana;}virtual AbstractPear* CreatePear() {return new JapanPear;}
};void test01() {AbstractFactory* factory = NULL;AbstractApple* apple = NULL;AbstractBanana* Banana = NULL;AbstractPear* Pear = NULL;//中国工厂factory = new ChinaFactory;apple = factory->CreateApple();Banana = factory->CreateBanana();Pear = factory->CreatePear();apple->showName();Banana->showName();Pear->showName();delete Pear;delete apple;delete Banana;delete factory;
}int main()
{test01();
}

Singleton 模式( 单例模式,针对一个类的唯一实例)
Singleton 模式是设计模式中最为简单、最为常见、最容易实现,也是最应该熟悉和掌握的模式。Singleton 模式就是一个类只创建一个唯一的对象,即一次创建多次使用。

实现单例模式的步骤:
1、构造函数私有化
2、增加静态私有的当前类的指针变量
3、提供静态对外接口,可以让用户获得单例对象

单例分为懒汉式和饿汉式

懒汉式:解决了饿汉式内存浪费问题,但是线程不安全的,可以通过互斥量mutex.lock()和mutex.unlock()来解决,懒汉用的比较多
饿汉式:还没有使用该单例对象,该单例对象就已经被加载到内存了,在对象过多时会造成内存浪费,饿汉模式会在程序启动时就创建单例对象,并且该对象会一直存在于内存中,即使在程序执行过程中没有被使用。这可能会导致内存浪费,特别是在单例对象比较大或者创建单例对象需要消耗大量资源的情况下。

这个是饿汉模式,返回的是一个静态变量,静态变量没运行就会产生数据

class Singleton {
private:static Singleton instance;Singleton() {}public:static Singleton& getInstance() {return instance;}void doSomething() {std::cout << "Singleton instance is doing something." << std::endl;}
};Singleton Singleton::instance;int main() {Singleton& singleton = Singleton::getInstance();singleton.doSomething();return 0;
}

这个是懒汉模式,返回的是一个静态变量指针,程序调用getinstance才会产生数据

#include <iostream>
#include <mutex>class Singleton {
private://类外定义成员变量static Singleton* instance;static std::mutex mutex;//构造函数私有化Singleton() {}public:static Singleton* getInstance() {if (instance == nullptr) {std::lock_guard<std::mutex> lock(mutex);if (instance == nullptr) {instance = new Singleton();}}return instance;}void doSomething() {std::cout << "Singleton instance is doing something." << std::endl;}
};Singleton* Singleton::instance = nullptr;
std::mutex Singleton::mutex;int main() {Singleton* singleton = Singleton::getInstance();singleton->doSomething();return 0;
}

相关文章:

c++设计模式之一创建型模式

1、创建型模式&#xff08;常见的设计模式&#xff09; Factory 模式&#xff08;工厂模式&#xff0c;被实例化的子类&#xff09; 在面向对象系统设计中经常可以遇到以下的两类问题&#xff1a; 下面是第一类问题和代码示例&#xff1a;我们经常会抽象出一些类的公共接口以…...

上古世纪台服注册账号+下载客户端全方位图文教程

又一款新的MMRPG游戏即将上线啦&#xff0c;游戏名称叫做《上古世纪》游戏采用传统MMO类型游戏的玩法&#xff0c;但是开发商采用了先进的游戏引擎&#xff0c;让玩家们可以享受到极致的视觉体验。同时游戏的背景是建立在大陆分崩离析的基础上。各个部落因为领地的原因纷纷开战…...

【Android】Android中继承Activity、Application和AppCompatActivity的区别

在 Android 开发中&#xff0c;Activity、Application 和 AppCompatActivity 是三个重要的类&#xff0c;它们各自有不同的作用和用途&#xff1a; 1. Activity Activity 是 Android 应用中的一个核心组件&#xff0c;代表了用户界面上的一个单一屏幕或交互界面。每个 Activi…...

SQLite 可以随可执行文件部署在用户机器吗

答案是&#xff1a;可以的。 sqlite 本身就是嵌入式的SQL数据库引擎&#xff0c;不需要单独的服务器进程。sqlite 直接读取和写入普通磁盘文件&#xff0c;sqlite 的整个数据库&#xff08;所有表、索引、触发器等&#xff09;都包含在单个磁盘文件中。所以 sqlite 很适合开发…...

大模型的开源不同于传统的开源软件

大模型的开源与传统的开源软件往往有一些不同之处&#xff0c;主要体现在以下几个方面&#xff1a; 数据和许可证的复杂性&#xff1a; 数据依赖性&#xff1a; 大模型通常需要大量的数据来进行训练&#xff0c;这些数据可能来自各种来源&#xff0c;包括公共数据集、专有数据集…...

基于PHP+MySql的留言管理系统的设计与实现

功能概述 网页留言板管理系统&#xff0c;用户层面分为普通用户和管理员&#xff0c;并设权限&#xff08;即后台留言管理系统普通用户不能访问&#xff0c;别人的留言自己不可以修改删除&#xff0c;未登录不能使用留言功能&#xff09;&#xff0c;功能包括用户登录注册、留…...

单目标应用:基于吸血水蛭优化器(Blood-Sucking Leech Optimizer,BSLO)的微电网优化(MATLAB代码)

一、微电网模型介绍 微电网多目标优化调度模型简介_vmgpqv-CSDN博客 参考文献&#xff1a; [1]李兴莘,张靖,何宇,等.基于改进粒子群算法的微电网多目标优化调度[J].电力科学与工程, 2021, 37(3):7 二、吸血水蛭优化器求解微电网 2.1算法简介 吸血水蛭优化器&#xff08;B…...

嵌入式工程师从0开始,到底该学什么,怎么学

在开始前刚好我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「嵌入式的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“666”之后私信回复“666”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff01;嵌入式是个大筐&#xff0…...

Redis-集群-环境搭建

文章目录 1、清空主从复制和哨兵模式留下的一些文件1.1、删除以rdb后缀名的文件1.2、删除主从复制的配置文件1.3、删除哨兵模式的配置文件 2、appendonly修改回no3、开启daemonize yes4、protect-mode no5、注释掉bind6、制作六个实例的配置文件6.1、制作配置文件redis6379.con…...

ITSG、COST-G、Tongji和WHU Level-2数据产品读取绘图(Matlab)

数据介绍&#xff1a; ICGEM International Center for Global Gravity Field Models (gfz-potsdam.de) ITSG 2018&#xff1a;Institute of Geodesy at Graz University of Technolog&#xff08;格拉茨理工大学大地测量研究所&#xff09; 2018版本&#xff0c;最高60阶球谐…...

linux(ubuntucentos)-安装libreoffice

因为需要在linux支持word文档和pdf之间的转换&#xff0c;调研验证后选择了libreoffice&#xff0c;在不同的服务器进行了安装&#xff0c;记录如下。 说明&#xff1a; 此处下载版本是7.6.7&#xff0c;如果网址不存在&#xff0c;可以访问http://mirrors.ustc.edu.cn/tdf/l…...

上海市计算机学会竞赛平台2023年9月月赛丙组点对之和(一)

题目描述 给定两个数列 &#x1d44e;1,&#x1d44e;2,…,&#x1d44e;&#x1d45b;a1​,a2​,…,an​ 与 &#x1d44f;1,&#x1d44f;2,…,&#x1d44f;&#x1d45b;b1​,b2​,…,bn​&#xff0c;保证这些数字是 11 到 &#x1d45b;n 之间的整数&#xff0c;请计算 …...

maven-jar-plugin在springboot中打包成普通引用的jar

如果您想要创建一个不包含Spring Boot特定结构的普通jar包&#xff08;例如&#xff0c;一个可以被其他项目作为依赖引用的库&#xff09;&#xff0c;您需要在pom.xml中添加maven-jar-plugin的配置。这里是一个示例配置&#xff0c;它将创建一个带有lib分类器的jar包&#xff…...

小型海外仓布局策略:高效利用有限空间,标准化3F流程

合理高效的仓库空间设计&#xff0c;不只是对大型海外仓很关键。对空间有限的小型海外仓来说或许价值更大。 本身仓储空间就有限&#xff0c;如果还没有科学规划&#xff0c;造成空间浪费&#xff0c;那将直接影响到核心业务的运转。 今天我们就给大家整理了对小型海外仓布局…...

【高考志愿】电气工程

目录 一、专业概述 二、专业特点 三、就业前景 四、选择学校 高考志愿选择电气工程是一个极具智慧和远见的决定&#xff0c;因为电气工程在当今社会中扮演着至关重要的角色。以下是对电气工程专业更为详细的解析&#xff1a; 一、专业概述 电气工程及其自动化专业&#xf…...

贪吃蛇项目:GameRun与GameEnd部分:游戏的主体运行与善后部分

准备工作&#xff1a;打印得分信息 在进行GameStart之前&#xff0c;我们需要在地图的右侧打印帮助信息&#xff0c;以及目前玩家的得分情况和一个食物在当前速度下的得分情况&#xff08;加速的状态下按比例增加食物的分数&#xff0c;减速的状态下则相反&#xff09;&#xf…...

mysql索引、事务以及存储引擎

目录 一、索引 1&#xff09;索引定义 ​2&#xff09;工作方式 3&#xff09;创建索引的依据 4&#xff09;索引类型 1、index普通索引 2、unique唯一索引 3、主键索引 4、多列组合索引 5、全文索引 5&#xff09;删除索引 6&#xff09;查看索引 7&#xff09;索…...

idea添加文档注释

一、easy javadoc插件 在settings的plugins中下载easy javadoc插件。 安装完成后重启idea&#xff0c;再次打开settings界面。会出现easyDoc相关配置。 二、设置模版以及使用 类描述模版参考设置&#xff1a; /** * 类描述 -> * * Author: ywz * Date: $Date$ */ 方法描述…...

python函数练习

1、编写函数&#xff0c;传入N&#xff0c;求123…N的和 def s_sum(num):i 1sum1 0while i < num:sum1 ii 1return sum1num int(input(请输入一个整数&#xff1a;)) print(和为:,s_sum(num))2、编写一个函数&#xff0c;定义一个列表&#xff0c;求列表中的最大值 d…...

基于PHP的奶茶商城系统

有需要请加文章底部Q哦 可远程调试 基于PHP的奶茶商城系统 一 介绍 此奶茶商城系统基于原生PHP开发&#xff0c;数据库mysql&#xff0c;ajax实现数据交换。系统角色分为用户和管理员。系统在原有基础上添加了糖度的选择。 技术栈 phpmysqlajaxphpstudyvscode 二 功能 用户…...

物联网“此用户无权修改接入点名称设置”解决方案

根本原因apns-conf.xml里面没有 符合 物理网卡 的配置 可以先加一个APN试一下&#xff0c;看看默认的MCC和MNC是什么 然后在”命令行“查询一下 adb shell sqlite3 /data/user_de/0/com.android.providers.telephony/databases/telephony.db "select * from carriers wh…...

网工常见面试题

1-10题 1.介绍TCP/IP四层、五层模型作用及每层包含的协议 TCP/IP四层模型 应用层&#xff1a; 作用&#xff1a;直接与应用程序交互&#xff0c;定义了应用程序如何通过网络发送数据。包含协议&#xff1a;HTTP&#xff08;网页浏览&#xff09;、FTP&#xff08;文件传输&…...

SQL实现UUIDv7

当我们选择数据库的主键类型时&#xff0c;通常会考虑自增数字或者 UUID。但是这两种类型都有优缺点&#xff0c;自增字段简单有序&#xff0c;性能良好&#xff0c;最大的问题是无法保证全局唯一性&#xff0c;分布式场景受限&#xff1b;UUID 具有全局唯一性&#xff0c;适合…...

2024期权交易佣金手续费最低是多少?期权交易有哪些成本?

显性成本 期权交易的显性成本包含期权交易的佣金和交易所费用&#xff0c;分别支付给券商和交易所&#xff0c;统一由券商代收。 佣金 期权佣金是期权交易时支付给券商的费用&#xff0c;佣金通常以交易金额的一定比例计算&#xff0c;可以是固定费用&#xff0c;也可以是滑…...

合合信息智能文档抽取:赋能不良资产管理行业的数字化转型

官.网地址&#xff1a;合合TextIn - 合合信息旗下OCR云服务产品 随着数字化浪潮的汹涌澎湃&#xff0c;全球各行各业正经历着前所未有的变革。人工智能技术的快速发展&#xff0c;以其独特的创新能力和应用潜力&#xff0c;正在深刻地改变着业务模式&#xff0c;推动产业效率的…...

【别再用Excel了!】这款免费可视化工具能帮你轻松提升效率

现代数据分析和展示的需求已经远远超出了传统工具的能力&#xff0c;尤其是在需要快速、直观和高效地处理复杂数据的情况下。山海鲸可视化通过其强大的功能和易用性&#xff0c;成为了设计师以及各类新手用户的理想选择。下面我就以一个可视化设计师的角度&#xff0c;和大家简…...

python holidays获取中国节日

在Python中&#xff0c;holidays库是一个流行的库&#xff0c;用于处理各种国家和地区的公共假期。然而&#xff0c;需要注意的是&#xff0c;截至2024年&#xff0c;holidays库的官方版本可能并不直接支持中国的所有节日。不过&#xff0c;我们可以通过扩展或自定义该类库来添…...

Jenkins流水线发布,一篇就解决你的所有疑惑

这次搭建的项目比较常规,前端是react写的,后端是springboot,并且由于是全栈开发,所以是在同一个项目中。接下来我演示下怎么用jenkins进行自动化发布。 1.jenkins必装插件 这里用到的是jenkinsFile主要是基于Groovy这个沙盒,有些前置插件。这里使用maven进行打包,所以需…...

安装zabbix时报错Could not resolve host: mirrors.huaweicloud.com;Unknown error解决办法

目录 1、问题原因 2、解决办法 3、知识拓展 DNS的区别 DNS配置文件解析 域名解析过程 4、书籍推荐 当安装Zabbix server&#xff0c;Web前端&#xff0c;agent时出现&#xff1a; [rootsc-zabbix-server ~]# yum install zabbix-server-mysql zabbix-agent安装过程中会出…...

【Linux】CentOS 7 安装配置 postfix 邮件服务器随笔

本文并不是完整配置教程&#xff0c;只是配置过程中零散代码随笔&#xff0c;不成系统 记录配置 PostFix 邮件服务器过程&#xff0c;由于经常用到&#xff0c;会不定时更新完善 yum install -y postfix dovecot cyrus-sasl-plain cyrus-sasl mailx# 设置hostname hostnamect…...