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、创建型模式(常见的设计模式) Factory 模式(工厂模式,被实例化的子类) 在面向对象系统设计中经常可以遇到以下的两类问题: 下面是第一类问题和代码示例:我们经常会抽象出一些类的公共接口以…...

上古世纪台服注册账号+下载客户端全方位图文教程
又一款新的MMRPG游戏即将上线啦,游戏名称叫做《上古世纪》游戏采用传统MMO类型游戏的玩法,但是开发商采用了先进的游戏引擎,让玩家们可以享受到极致的视觉体验。同时游戏的背景是建立在大陆分崩离析的基础上。各个部落因为领地的原因纷纷开战…...
【Android】Android中继承Activity、Application和AppCompatActivity的区别
在 Android 开发中,Activity、Application 和 AppCompatActivity 是三个重要的类,它们各自有不同的作用和用途: 1. Activity Activity 是 Android 应用中的一个核心组件,代表了用户界面上的一个单一屏幕或交互界面。每个 Activi…...
SQLite 可以随可执行文件部署在用户机器吗
答案是:可以的。 sqlite 本身就是嵌入式的SQL数据库引擎,不需要单独的服务器进程。sqlite 直接读取和写入普通磁盘文件,sqlite 的整个数据库(所有表、索引、触发器等)都包含在单个磁盘文件中。所以 sqlite 很适合开发…...
大模型的开源不同于传统的开源软件
大模型的开源与传统的开源软件往往有一些不同之处,主要体现在以下几个方面: 数据和许可证的复杂性: 数据依赖性: 大模型通常需要大量的数据来进行训练,这些数据可能来自各种来源,包括公共数据集、专有数据集…...

基于PHP+MySql的留言管理系统的设计与实现
功能概述 网页留言板管理系统,用户层面分为普通用户和管理员,并设权限(即后台留言管理系统普通用户不能访问,别人的留言自己不可以修改删除,未登录不能使用留言功能),功能包括用户登录注册、留…...

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

嵌入式工程师从0开始,到底该学什么,怎么学
在开始前刚好我有一些资料,是我根据网友给的问题精心整理了一份「嵌入式的资料从专业入门到高级教程」, 点个关注在评论区回复“666”之后私信回复“666”,全部无偿共享给大家!!!嵌入式是个大筐࿰…...

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)
数据介绍: ICGEM International Center for Global Gravity Field Models (gfz-potsdam.de) ITSG 2018:Institute of Geodesy at Graz University of Technolog(格拉茨理工大学大地测量研究所) 2018版本,最高60阶球谐…...
linux(ubuntucentos)-安装libreoffice
因为需要在linux支持word文档和pdf之间的转换,调研验证后选择了libreoffice,在不同的服务器进行了安装,记录如下。 说明: 此处下载版本是7.6.7,如果网址不存在,可以访问http://mirrors.ustc.edu.cn/tdf/l…...
上海市计算机学会竞赛平台2023年9月月赛丙组点对之和(一)
题目描述 给定两个数列 𝑎1,𝑎2,…,𝑎𝑛a1,a2,…,an 与 𝑏1,𝑏2,…,𝑏𝑛b1,b2,…,bn,保证这些数字是 11 到 𝑛n 之间的整数,请计算 …...
maven-jar-plugin在springboot中打包成普通引用的jar
如果您想要创建一个不包含Spring Boot特定结构的普通jar包(例如,一个可以被其他项目作为依赖引用的库),您需要在pom.xml中添加maven-jar-plugin的配置。这里是一个示例配置,它将创建一个带有lib分类器的jar包ÿ…...

小型海外仓布局策略:高效利用有限空间,标准化3F流程
合理高效的仓库空间设计,不只是对大型海外仓很关键。对空间有限的小型海外仓来说或许价值更大。 本身仓储空间就有限,如果还没有科学规划,造成空间浪费,那将直接影响到核心业务的运转。 今天我们就给大家整理了对小型海外仓布局…...
【高考志愿】电气工程
目录 一、专业概述 二、专业特点 三、就业前景 四、选择学校 高考志愿选择电气工程是一个极具智慧和远见的决定,因为电气工程在当今社会中扮演着至关重要的角色。以下是对电气工程专业更为详细的解析: 一、专业概述 电气工程及其自动化专业…...

贪吃蛇项目:GameRun与GameEnd部分:游戏的主体运行与善后部分
准备工作:打印得分信息 在进行GameStart之前,我们需要在地图的右侧打印帮助信息,以及目前玩家的得分情况和一个食物在当前速度下的得分情况(加速的状态下按比例增加食物的分数,减速的状态下则相反)…...

mysql索引、事务以及存储引擎
目录 一、索引 1)索引定义 2)工作方式 3)创建索引的依据 4)索引类型 1、index普通索引 2、unique唯一索引 3、主键索引 4、多列组合索引 5、全文索引 5)删除索引 6)查看索引 7)索…...

idea添加文档注释
一、easy javadoc插件 在settings的plugins中下载easy javadoc插件。 安装完成后重启idea,再次打开settings界面。会出现easyDoc相关配置。 二、设置模版以及使用 类描述模版参考设置: /** * 类描述 -> * * Author: ywz * Date: $Date$ */ 方法描述…...
python函数练习
1、编写函数,传入N,求123…N的和 def s_sum(num):i 1sum1 0while i < num:sum1 ii 1return sum1num int(input(请输入一个整数:)) print(和为:,s_sum(num))2、编写一个函数,定义一个列表,求列表中的最大值 d…...

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

JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...
synchronized 学习
学习源: https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖,也要考虑性能问题(场景) 2.常见面试问题: sync出…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...

1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...

04-初识css
一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...

自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...
Element Plus 表单(el-form)中关于正整数输入的校验规则
目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入(联动)2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...
【Go语言基础【13】】函数、闭包、方法
文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数(函数作为参数、返回值) 三、匿名函数与闭包1. 匿名函数(Lambda函…...
虚拟电厂发展三大趋势:市场化、技术主导、车网互联
市场化:从政策驱动到多元盈利 政策全面赋能 2025年4月,国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》,首次明确虚拟电厂为“独立市场主体”,提出硬性目标:2027年全国调节能力≥2000万千瓦࿰…...