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;
}

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

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

相关文章

解决数据丢失问题的MacOS 数据恢复方法

每个人都经历过 Mac 硬盘或 USB 驱动器、数码相机、SD/存储卡等数据丢失的情况。我们中的一些人可能认为已删除或格式化的数据将永远丢失&#xff0c;因此就此作罢。对于 macOS 用户来说&#xff0c;当文件被删除时&#xff0c;垃圾箱已被清空&#xff0c;他们可能不知道如何恢…

pytorch lighting: Trying to resize storage that is not resizable

问题 在用pytorch lighting进行训练时碰到如下错误 即 Trying to resize storage that is not resizable 。 解决方案 在dataloader采样图片以及label时&#xff0c;保证每次采样的图片的分辨率不变。

Mistral AI 发布 Codestral-22B,精通 80+ 编程语言,22B 参数超越 70B Code Llama

前言 大型语言模型 (LLM) 在代码生成领域展现出巨大的潜力&#xff0c;但现有的模型在支持的编程语言数量、生成速度和代码质量方面仍存在局限性。法国 AI 独角兽 Mistral AI 近期发布了其首款代码生成模型 Codestral-22B&#xff0c;宣称在多项指标上超越了 GPT-4 和 Llama3&…

健康与生活助手:Kompas AI的高效应用

一、引言 在现代社会&#xff0c;随着生活节奏的加快和工作压力的增加&#xff0c;人们的健康问题日益凸显。健康管理已经成为每个人关注的重点。Kompas AI作为一款智能助手&#xff0c;通过其先进的人工智能技术&#xff0c;为用户提供全面的健康管理服务&#xff0c;帮助用户…

JavaSE 利用正则表达式进行本地和网络爬取数据(爬虫)

爬虫 正则表达式的作用 作用1&#xff1a;校验字符串是满足规则 作用2&#xff1a;在一段文本中查找满足需要的内容 本地爬虫和网络爬虫 Pattern类 表示正则表达式 Matter类 文本编译器&#xff0c;作用按照正则表达式的规则去读取字符串&#xff0c;从头开始读取&#xf…

【idea】gradle多模块构建项目内存溢出终止问题解决

背景 idea构建多模块项目&#xff0c;构建报错 Daemon is stopping immediately JVM garbage collector thrashing and after running out of JVM memory 解决 进到下图目录下 在文件管理中进入上面目录添加gradle.properties文件&#xff0c;内容如下 org.gradle.jvmargs-…

hive on spark 的架构和常见问题 - hive on spark 使用的是 yarn client 模式还是 yarn cluster 模式?

hive on spark 的架构和常见问题 - hive on spark 使用的是 yarn client 模式还是 yarn cluster 模式&#xff1f; 1. 回顾下 spark 的架构图和部署模式 来自官方的经典的 spark 架构图如下&#xff1a; 上述架构图&#xff0c;从进程的角度来讲&#xff0c;有四个角色/组件&…

【面试干货】抽象类与接口的区别

【面试干货】抽象类与接口的区别 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 在Java编程中&#xff0c;抽象类和接口是两个非常重要的概念&#xff0c;它们都为代码的可扩展性和复用性提供了基础。但是&#xff0c;它们之间也有一些明显…

maxwell源码编译安装部署

目录 1、组件环境 2、maxwell安装前提 3、maxwell安装 3.1、maxwell下载 3.1.1、最新版本下载 ​编辑 3.1.2、历史版本下载 3.2、maxwell安装 3.3、maxwell配置 3.2.1、mysql开启binlog 3.3.2、maxwell元数据配置 3.3.3、maxwell配置任务 4、maxwell部署问题 4.1、utf…

django学习入门系列之第三点《CSS基础样式介绍1》

文章目录 高度和宽度块级标签|行内标签的转换字体和颜色往期回顾 高度和宽度 如果在块级标签内&#xff0c;单独定义高度的话&#xff0c;宽度会默认拉满 使用百分比的时候 如果是块级标签&#xff0c;宽度可以用百分比&#xff0c;高度用不了&#xff08;使用起来没效果&…

Mac OS 安装frida

安装frida和frida-tools Python是基础&#xff0c;提前装好Python 终端执行 python3 -m pip install frida 如果出现error 按照提示处理 信息提示&#xff1a;brew install pipx 于是终端执行&#xff1a; brew install pipx 安装frida&#xff1a; pipx install frida…

VMware ESXi 8.0U2c macOS Unlocker OEM BIOS Huawei (华为) FusionServer 定制版

VMware ESXi 8.0U2c macOS Unlocker & OEM BIOS Huawei (华为) FusionServer 定制版 ESXi 8.0U2 标准版&#xff0c;Dell (戴尔)、HPE (慧与)、Lenovo (联想)、Inspur (浪潮)、Cisco (思科)、Hitachi (日立)、Fujitsu (富士通)、NEC (日电)、Huawei (华为)、xFusion (超聚…

前端vue实战项目结构、常用编辑器vs code 配置

5.Complete JSDoc Tags 6.Custom CSS and JS Loader 7.Debugger for Chrome 8.EditorConfig for VS Code 9.ESLint ☆☆☆ 10.gitignore 11.GitLens — Git supercharged 12.npm 13.PostCSS syntax !important 14.Vetur ☆ 15.vscode-icons 16.vue-i18n 17.Markdow…

2024年最值得推荐的10款免费数据可视化工具!

数据可视化之所以受欢迎&#xff0c;不仅因为它简化了我们查看繁杂数据的方式&#xff0c;还在于数据可视化可以加快我们获取数据信息的速度。但是对于初学者来说&#xff0c;使用数据可视化工具并不能够快速上手。因此本篇文章特意为大家列出了10款免费的数据可视化工具&#…

html做一个画柱形图的软件

你可以使用 HTML、CSS 和 JavaScript 创建一个简单的柱形图绘制软件。为了方便起见&#xff0c;我们可以使用一个流行的 JavaScript 图表库&#xff0c;比如 Chart.js&#xff0c;它能够简化创建和操作图表的过程。 以下是一个完整的示例&#xff0c;展示如何使用 HTML 和 Cha…

码蹄集 BD202401 补给

错误解法&#xff1a;简单将取半前后的综合排序后取最小值&#xff0c;这样没有考虑这样一种情况&#xff1a;取半的时机不对&#xff0c;也许取半某个大一点的P之后反而能进一步取一个补给点了呢&#xff1f;&#xff1f;对不对。这样简单排序只不过是“最省钱”的一种&#x…

Cocos引擎加密方案解析

据2023年数据显示&#xff0c;Cocos引擎全球游戏市场的占有率约为20%&#xff0c;国内手游占有率约为40%&#xff0c;在国内手游市场中&#xff0c;不少热门游戏均为Cocos引擎研发&#xff0c;如《捕鱼达人》、《梦幻西游》、《剑与远征》等。 而在近年来国内火热的小游戏赛道…

java实现分类下拉树,点击时对应搜索---后端逻辑

一直想做分类下拉&#xff0c;然后选择后搜索的页面&#xff0c;正好做项目有了明确的需求&#xff0c;查找后发现el-tree的构件可满足需求&#xff0c;数据要求为&#xff1a;{ id:1, label:name, childer:[……] }形式的&#xff0c;于是乎&#xff0c;开搞&#xff01; 一…

算法训练营day15--110.平衡二叉树+ 257. 二叉树的所有路径+ 404.左叶子之和+222.完全二叉树的节点个数

一、110.平衡二叉树 题目链接&#xff1a;https://leetcode.cn/problems/balanced-binary-tree/ 文章讲解&#xff1a;https://programmercarl.com/0110.%E5%B9%B3%E8%A1%A1%E4%BA%8C%E5%8F%89%E6%A0%91.html 视频讲解&#xff1a;https://www.bilibili.com/video/BV1Ug411S7m…

体育时间:“中国第一”的出海代表们,一致瞄准了这一赛道?

2024年无疑又是一个体育赛事超级大年。 从1月的亚洲杯&#xff0c;2月的世乒团体锦标赛、第14届冬运会、到6月欧洲杯与美洲杯隔空对决&#xff0c;巴黎奥运会也将在7月盛大开赛&#xff0c;随后则还有8月的巴黎残奥会&#xff0c;对于期待万分的体育粉丝们&#xff0c;这将是极…