23种设计模式——创建型模式
设计模式
文章目录
- 设计模式
- 创建型模式
- 单例模式 [1-小明的购物车](https://kamacoder.com/problempage.php?pid=1074)
- 工厂模式 [2-积木工厂](https://kamacoder.com/problempage.php?pid=1076)
- 抽象⼯⼚模式 [3-家具工厂](https://kamacoder.com/problempage.php?pid=1077)
- 建造者模式 [4-⾃⾏⻋加⼯](https://kamacoder.com/problempage.php?pid=1077)
- 原型模式 [5-矩形原型](https://kamacoder.com/problempage.php?pid=1083)
创建型模式
单例模式 1-小明的购物车
单例模式是⼀种创建型设计模式, 它的核⼼思想是保证⼀个类只有⼀个实例,并提供⼀个全局访问点来访问这个实
例。
- 只有⼀个实例的意思是,在整个应⽤程序中(进程),只存在该类的⼀个实例对象,⽽不是创建多个相同类型的对象。
- 全局访问点的意思是,为了让其他类能够获取到这个唯⼀实例,该类提供了⼀个全局访问点(通常是⼀个静态 ⽅法),通过这个⽅法就能获得实例
#include <iostream>
#include <unordered_map>
#include <vector>
#include<mutex>
#include<atomic>class ShoppingCartManager {
private:std::unordered_map<std::string, int> cart;std::vector<std::string> order; // 保持顺序// 私有构造函数ShoppingCartManager() {}static std::mutex m_mutex;//static ShoppingCartManager* m_cart;static std::atomic<ShoppingCartManager*> m_atomic; //使用原子变量将对象指针保存public:// 获取购物车实例static ShoppingCartManager* getInstance() {ShoppingCartManager* m_cart = m_atomic.load();if (m_cart == nullptr) {m_mutex.lock();m_cart = m_atomic.load();if (m_cart == nullptr) {m_cart = new ShoppingCartManager;m_atomic.store(m_cart); //保存对象指针}m_mutex.unlock();}return m_cart;}// 添加商品void addToCart(const std::string& itemName, int quantity) {if (cart.find(itemName) == cart.end()) { //如果cart里面没有该货物order.push_back(itemName); //注意这里是order,为了使得货物和数量能对齐}cart[itemName] += quantity;}// 查看商品void viewCart() const {for (const auto& itemName : order) { //这里按照顺序读取货物,保证有序输出;若只用unordered_map,无法保证有序std::cout << itemName << " " << cart.at(itemName) << std::endl;}}
};//ShoppingCartManager* ShoppingCartManager::m_cart = nullptr;
std::atomic<ShoppingCartManager*> ShoppingCartManager::m_atomic;
std::mutex ShoppingCartManager::m_mutex;int main() {std::string itemName;int quantity;ShoppingCartManager* cart = ShoppingCartManager::getInstance();while (std::cin >> itemName >> quantity) {cart->addToCart(itemName, quantity);}cart->viewCart();return 0;
}
使用静态局部变量保证多线程下的资源安全
工厂模式 2-积木工厂
⼯⼚⽅法模式也是⼀种创建型设计模式,简单⼯⼚模式只有⼀个⼯⼚类,负责创建所有产品,如果要添加新的产品,通常需要修改⼯⼚类的代码。⽽⼯⼚⽅法模式引⼊了抽象⼯⼚和具体⼯⼚的概念,每个具体⼯⼚只负责创建⼀个具体产品,添加新的产品只需要添加新的⼯⼚类⽽⽆需修改原来的代码,这样就使得产品的⽣产更加灵活,⽀持扩展,符合开闭原则。
⼯⼚⽅法模式分为以下⼏个⻆⾊:
抽象⼯⼚:⼀个接⼝,包含⼀个
- 抽象的⼯⼚⽅法(⽤于创建产品对象)。
- 具体⼯⼚:实现抽象⼯⼚接⼝,创建具体的产品。
- 抽象产品:定义产品的接⼝。
- 具体产品:实现抽象产品接⼝,是⼯⼚创建的对象。
// 表驱动 + lambda 表达式#include<iostream>
#include<bits/stdc++.h>using namespace std;class Shape {
public:virtual void show() = 0;
};class Circle : public Shape {
public:void show() {cout << "Circle Block" << endl;}
};class Square : public Shape {
public:void show () {cout << "Square Block" << endl;}
};class ShapeFactory {
public:virtual Shape* produce() = 0;
};class CircleFactory : public ShapeFactory {
public:Shape* produce() {return new Circle();}
};class SquareFactory : public ShapeFactory {
public:Shape* produce() {return new Square();}
};unordered_map<string, function<ShapeFactory*()>> m {{"Circle", [](){ return new CircleFactory();}},{"Square", [](){ return new SquareFactory();}},
};class BlocksFactory {
public:vector<Shape*> blocks;void CreateBlocks(string& type, int count) {ShapeFactory* sf = m[type]();Shape* s = sf -> produce();for (int i = 0; i < count; i++) {blocks.push_back(s);}}void Print() {for (const auto& s : blocks) {s -> show();}}
};int main() {int produceTime;cin >> produceTime;string type;int count;BlocksFactory* bf = new BlocksFactory();for (int i = 0; i < produceTime; i++) {cin >> type >> count;bf->CreateBlocks(type, count);}bf->Print();return 0;
}
抽象⼯⼚模式 3-家具工厂
抽象⼯⼚模式包含多个抽象产品接⼝,多个具体产品类,⼀个抽象⼯⼚接⼝和多个具体⼯⼚,每个具体⼯⼚负责创建⼀组相关的产品。
- 抽象产品接⼝ AbstractProduct : 定义产品的接⼝,可以定义多个抽象产品接⼝,⽐如说沙发、椅⼦、茶⼏都是抽象产品。
- 具体产品类 ConcreteProduct : 实现抽象产品接⼝,产品的具体实现,古典⻛格和沙发和现代⻛格的沙发都是具体产品。
- 抽象⼯⼚接⼝AbstractFactory : 声明⼀组⽤于创建产品的⽅法,每个⽅法对应⼀个产品。
- 具体⼯⼚类 ConcreteFactory : 实现抽象⼯⼚接⼝,,负责创建⼀组具体产品的对象,在本例中,⽣产古典⻛格的⼯⼚和⽣产现代⻛格的⼯⼚都是具体实例.
#include <iostream>
#include <string>
#include <unordered_map>
#include <functional>using namespace std;class Sofa {
public:virtual void info() = 0;
};class ModernSofa : public Sofa {
public:void info() override {cout << "modern sofa" << endl;};
};class ClassicalSofa : public Sofa {
public:void info() override {cout << "classical sofa" << endl;};
};class Chair {
public:virtual void info() = 0;
};class ModernChair : public Chair {
public:void info() override {cout << "modern chair" << endl;};
};class ClassicalChair : public Chair {
public:void info() override {cout << "classical chair" << endl;};
};class Factory {
public:virtual Sofa *buildSofa() = 0;virtual Chair *buildChair() = 0;
};class ModernFactory : public Factory {
public:Sofa *buildSofa() override{return new ModernSofa();}Chair *buildChair() override{return new ModernChair();}
};class ClassicalFactory : public Factory {
public:Sofa *buildSofa() override{return new ClassicalSofa();}Chair *buildChair() override{return new ClassicalChair();}
};unordered_map<string, function<Factory*()>> factoryTable {{"modern", [](){ return new ModernFactory(); }},{"classical", [](){ return new ClassicalFactory(); }}
};int main()
{int loop;cin >> loop;string type;while (loop--){cin >> type;Factory *f = factoryTable[type]();Chair *c = f->buildChair();Sofa *s = f->buildSofa();c->info();s->info();}return 0;
}
建造者模式 4-⾃⾏⻋加⼯
建造者模式(也被成为⽣成器模式),是⼀种创建型设计模式,软件开发过程中有的时候需要创建很复杂的对象,⽽建造者模式的主要思想是将对象的构建过程分为多个步骤,并为每个步骤定义⼀个抽象的接⼝。具体的构建过程由实现了这些接⼝的具体建造者类来完成。同时有⼀个指导者类负责协调建造者的⼯作,按照⼀定的顺序或逻辑来执⾏构建步骤,最终⽣成产品。
- 产品Product:被构建的复杂对象, 包含多个组成部分。
- 抽象建造者 Builder : 定义构建产品各个部分的抽象接⼝和⼀个返回复杂产品的⽅法
- 具体建造者 getResult Concrete Builder :实现抽象建造者接⼝,构建产品的各个组成部分,并提供⼀个⽅法返回最终的产品。
- 指导者 Director :调⽤具体建造者的⽅法,按照⼀定的顺序或逻辑来构建产品。
使⽤建造者模式有下⾯⼏处优点:
- 使⽤建造者模式可以将⼀个复杂对象的构建与其表示分离,通过将构建复杂对象的过程抽象出来,可以使客户端代码与具体的构建过程解耦
- 同样的构建过程可以创建不同的表示,可以有多个具体的建造者(相互独⽴),可以更加灵活地创建不同组合的对象
#include <iostream>
#include <string>
#include <unordered_map>
#include <functional>using namespace std;class Sofa {
public:virtual void info() = 0;
};class ModernSofa : public Sofa {
public:void info() override {cout << "modern sofa" << endl;};
};class ClassicalSofa : public Sofa {
public:void info() override {cout << "classical sofa" << endl;};
};class Chair {
public:virtual void info() = 0;
};class ModernChair : public Chair {
public:void info() override {cout << "modern chair" << endl;};
};class ClassicalChair : public Chair {
public:void info() override {cout << "classical chair" << endl;};
};class Factory {
public:virtual Sofa *buildSofa() = 0;virtual Chair *buildChair() = 0;
};class ModernFactory : public Factory {
public:Sofa *buildSofa() override{return new ModernSofa();}Chair *buildChair() override{return new ModernChair();}
};class ClassicalFactory : public Factory {
public:Sofa *buildSofa() override{return new ClassicalSofa();}Chair *buildChair() override{return new ClassicalChair();}
};unordered_map<string, function<Factory*()>> factoryTable {{"modern", [](){ return new ModernFactory(); }},{"classical", [](){ return new ClassicalFactory(); }}
};int main()
{int loop;cin >> loop;string type;while (loop--){cin >> type;Factory *f = factoryTable[type]();Chair *c = f->buildChair();Sofa *s = f->buildSofa();c->info();s->info();}return 0;
}
原型模式 5-矩形原型
如果⼀个对象的创建过程⽐较复杂时(⽐如需要经过⼀系列的计算和资源消耗),那每次创建该对象都需要消耗资源,⽽通过原型模式就可以复制现有的⼀个对象来迅速创建/克隆⼀个新对象,不必关⼼具体的创建细节,可以降低对象创建的成本。
原型模式的基本结构
实现原型模式需要给【原型对象】声明⼀个克隆⽅法,执⾏该⽅法会创建⼀个当前类的新对象,并将原始对象中的成员变量复制到新⽣成的对象中,⽽不必实例化。并且在这个过程中只需要调⽤原型对象的克隆⽅法,⽽⽆需知道原型对象的具体类型。
原型模式包含两个重点模块:
- 抽象原型接⼝ prototype : 声明⼀个克隆⾃身的⽅法
- 具体原型类 ConcretePrototype : 实现 clone ⽅法,复制当前对象并返回⼀个新对象。在客户端代码中,可以声明⼀个具体原型类的对象,然后调⽤clone() ⽅法复制原对象⽣成⼀个新的对象
#include<iostream>
#include<string>
using namespace std;class Prototype {
public:virtual Prototype* clone() = 0;virtual void print() = 0;virtual ~Prototype() {}
};class Triangle : public Prototype{
private:string color;int width, height;
public:Triangle(const string& color, int width, int height): color(color), width(width), height(height) {}Prototype* clone() override {return new Triangle(this->color, this->width, this->height);}void print() override {cout<<"Color: "<<this->color<<", Width: "<<this->width<<", Height: "<<this->height<<endl;}
};int main(){int n;string color;int w,h;cin >> color >> w >> h;cin >> n;while(n--){Prototype* original = new Triangle(color, w, h);Prototype* cloned = original->clone();cloned->print();delete original;delete cloned;}return 0;
}
相关文章:
23种设计模式——创建型模式
设计模式 文章目录 设计模式创建型模式单例模式 [1-小明的购物车](https://kamacoder.com/problempage.php?pid1074)工厂模式 [2-积木工厂](https://kamacoder.com/problempage.php?pid1076)抽象⼯⼚模式 [3-家具工厂](https://kamacoder.com/problempage.php?pid1077)建造者…...
idm究竟有哪些优势
IDM(Internet Download Manager)是一款广受好评的下载管理工具,其主要优势包括: 高速下载:IDM支持最大32线程的下载,可以显著提升下载速度1。文件分类下载:IDM可以根据文件后缀进行分类&#x…...
如何学习Golang语言!
第一部分:Go语言概述 起源与设计哲学:Go语言由Robert Griesemer、Rob Pike和Ken Thompson三位Google工程师设计,旨在解决现代编程中的一些常见问题,如编译速度、运行效率和并发编程。主要特点:Go语言的语法简单、编译…...
Redis系列之淘汰策略介绍
Redis系列之淘汰策略介绍 文章目录 为什么需要Redis淘汰策略?Redis淘汰策略分类Redis数据淘汰流程源码验证淘汰流程Redis中的LRU算法Redis中的LFU算法 为什么需要Redis淘汰策略? 由于Redis内存是有大小的,当内存快满的时候,又没有…...
sql 调优
sql 调优 SQL调优是一个复杂的过程,涉及多个方面,包括查询优化、索引优化、表结构优化等。以下是一些基本的SQL调优策略: 使用索引:确保查询中涉及的列都有适当的索引。 查询优化:避免使用SELECT *,只选取…...
【UML用户指南】-13-对高级结构建模-包
目录 1、名称 2、元素 3、可见性 4、引入与引出 用包把建模元素安排成可作为一个组来处理的较大组块。可以控制这些元素的可见性,使一些元素在包外是可见的,而另一些元素要隐藏在包内。也可以用包表示系统体系结构的不同视图。 狗窝并不复杂&#x…...
前端面试题日常练-day63 【面试题】
题目 希望这些选择题能够帮助您进行前端面试的准备,答案在文末 1. TypeScript中,以下哪个关键字用于声明一个类的构造函数? a) constructor b) init c) create d) initialize 2. 在TypeScript中,以下哪个符号用于声明可选的函…...
GAN的入门理解
这一篇主要是关于生成对抗网络的模型笔记,有一些简单的证明和原理,是根据李宏毅老师的课程整理的,下面有链接。本篇文章主要就是梳理基础的概念和训练过程,如果有什么问题的话也可以指出的。 李宏毅老师的课程链接 1.概述 GAN是…...
43【PS 作图】颜色速途
1 通过PS让画面细节模糊,避免被过多的颜色干扰 2 分析画面的颜色 3 作图 参考网站: 色感不好要怎么提升呢?分享一下我是怎么练习色感的!_哔哩哔哩_bilibili https://www.bilibili.com/video/BV1h1421Z76p/?spm_id_from333.1007.…...
定个小目标之刷LeetCode热题(13)
今天来看看这道题,介绍两种解法 第一种动态规划,代码如下 class Solution {public int maxSubArray(int[] nums) {int pre 0, maxAns nums[0];for (int x : nums) {// 计算当前最大前缀和pre Math.max(pre x, x);// 更新最大前缀和maxAns Math.ma…...
【AI大模型】Prompt Engineering
目录 什么是提示工程(Prompt Engineering) Prompt 调优 Prompt 的典型构成 「定义角色」为什么有效? 防止 Prompt 攻击 攻击方式 1:著名的「奶奶漏洞」 攻击方式 2:Prompt 注入 防范措施 1:Prompt 注…...
centos安装vscode的教程
centos安装vscode的教程 步骤一:打开vscode官网找到历史版本 历史版本链接 步骤二:找到文件下载的位置 在命令行中输入(稍等片刻即可打开): /usr/share/code/bin/code关闭vscode后,可在应用程序----编程…...
面试题------>MySQL!!!
一、连接查询 ①:左连接left join (小表在左,大表在右) ②:右连接right join(小表在右,大表在左) 二、聚合函数 SQL 中提供的聚合函数可以用来统计、求和、求最值等等 COUNT&…...
英伟达:史上最牛一笔天使投资
200万美元的天使投资,让刚成立就面临倒闭风险的英伟达由危转安,并由此缔造了一个2.8万亿美元的市值神话。 这是全球风投史上浓墨重彩的一笔。 前不久,黄仁勋在母校斯坦福大学的演讲中,提到了人生中的第一笔融资——1993年&#x…...
PDF分页处理:技术与实践
引言 在数字化办公和学习中,PDF文件因其便携性和格式稳定性而广受欢迎。然而,处理大型PDF文件时,我们经常需要将其拆分成单独的页面,以便于管理和分享。本文将探讨如何使用Python编程语言和一些流行的库来实现PDF文件的分页处理。…...
数据可视化——pyecharts库绘图
目录 官方文档 使用说明: 点击基本图表 可以点击你想要的图表 安装: 一些例图: 柱状图: 效果: 折线图: 效果: 环形图: 效果: 南丁格尔图(玫瑰图&am…...
Python的return和yield,哪个是你的菜?
目录 1、return基础介绍 📚 1.1 return用途:数据返回 1.2 return执行:函数终止 1.3 return深入:无返回值情况 2、yield核心概念 🍇 2.1 yield与迭代器 2.2 生成器函数构建 2.3 yield的暂停与续行特性 3、retur…...
持续总结中!2024年面试必问 20 道分布式、微服务面试题(七)
上一篇地址:持续总结中!2024年面试必问 20 道分布式、微服务面试题(六)-CSDN博客 十三、请解释什么是服务网格(Service Mesh)? 服务网格(Service Mesh)是一种用于处理服…...
AJAX 跨域
这里写目录标题 同源策略JSONPJSONP 是怎么工作的JSONP 的使用原生JSONP实践CORS 同源策略 同源: 协议、域名、端口号 必须完全相同、 当然网页的URL和AJAX请求的目标资源的URL两者之间的协议、域名、端口号必须完全相同。 AJAX是默认遵循同源策略的,不…...
3 数据类型、运算符与表达式-3.1 C语言的数据类型和3.2 常量与变量
数据类型 基本类型 整型字符型实型(浮点型) 单精度型双精度型 枚举类型 构造类型 数组类型结构体类型共用体类型 指针类型空类型 #include <stdio.h> #include <string.h> #include <stdbool.h> // 包含布尔类型定义 // 常量和符号常量 #define PRICE 30//…...
NSSCTF-Web题目5
目录 [SWPUCTF 2021 新生赛]error 1、题目 2、知识点 3、思路 [LitCTF 2023]作业管理系统 1、题目 2、知识点 3、思路 [HUBUCTF 2022 新生赛]checkin 1、题目 2、知识点 3、思路 [SWPUCTF 2021 新生赛]error 1、题目 2、知识点 数据库注入、报错注入 3、思路 首先…...
cnvd_2015_07557-redis未授权访问rce漏洞复现-vulfocus复现
1.复现环境与工具 环境是在vulfocus上面 工具:GitHub - vulhub/redis-rogue-getshell: redis 4.x/5.x master/slave getshell module 参考攻击使用方式与原理:https://vulhub.org/#/environments/redis/4-unacc/ 2.复现 需要一个外网的服务器做&…...
免费,C++蓝桥杯等级考试真题--第7级(含答案解析和代码)
C蓝桥杯等级考试真题--第7级 答案:D 解析:步骤如下: 首先,--a 操作会使 a 的值减1,因此 a 变为 3。判断 a > b 即 3 > 3,此时表达式为假,因为 --a 后 a 并不大于 b。因此,程…...
python为什么要字符串格式化
Python2.6 开始,新增了一种格式化字符串的函数 str.format(),它增强了字符串格式化的功能。相对于老版的%格式方法,它有很多优点。 1.在%方法中%s只能替代字符串类型,而在format中不需要理会数据类型; 2.单个参数可以…...
go语言后端开发学习(三)——基于validator包实现接口校验
前言 在我们开发模块的时候,有一个问题是我们必须要去考虑的,它就是如何进行入参校验,在gin框架的博客中我就介绍过一些常见的参数校验,大家可以参考gin框架学习笔记(四) ——参数绑定与参数验证,而这个其实也不是能够完全应对我…...
系统架构设计师【补充知识】: 应用数学 (核心总结)
一、 图论之最小生成树 (1)定义: 在连通的带权图的所有生成树中,权值和最小的那棵生成树(包含图中所有顶点的树),称作最小生成树。 (2)针对问题: 带权图的最短路径问题。 (3)最小生成树的解法有普里姆(Prim)算法和克鲁斯卡尔(Kruskal)算法,我…...
【ArcGIS微课1000例】0118:一文讲清楚tif(geotiff)栅格数据格式
文章目录 一、Tiff概述二、GeoTiff概述1. ovr文件2. tfw文件3. xml文件4. dbf文件一、Tiff概述 TIFF(Tagged Image File Format)是一种常见的图像文件格式,它被广泛用于存储和传输各种类型的图像数据。下面是对TIFF格式数据的介绍: 图像存储:TIFF格式可以存储多通道的位…...
调用第三方API --------------Python篇
在项目开发过程中,可能需要调用第三方的一些API或者公司提供的数据接口来得到相应的数据或者实现对应的功能。 因此API的调用和数据接口的访问都是做数据分析的一个常用操作,如何快速实现API和数据接口的调用,网上一般提供很多语言版本&#…...
Web自动化测试-掌握selenium工具用法,使用WebDriver测试Chrome/FireFox网页(Java
目录 一、在Eclipse中构建Maven项目 1.全局配置Maven 2.配置JDK路径 3.创建Maven项目 4.引入selenium-java依赖 二、Chrome自动化脚本编写 1.创建一个ChromeTest类 2.测试ChromeDriver 3.下载chromedriver驱动 4.在脚本中通过System.setProperty方法指定chromedriver的…...
maven多模块项目搭建
文章目录 创建方式创建父项目创建子模块 目录结构示例父模块模块A模块B(并在模块B中引入模块A) 注意事项 创建方式 创建父项目 #创建文件夹后,进入目录,执行以下命令 PS D:\demo> mvn archetype:generate #将输出很多模板&am…...
ubuntu系统做网站/seo网站关键词
题目描述 一些数字可能拥有以下的性质: 性质 1:是偶数; 性质 2:大于 4 且不大于 12。 小A 喜欢这两个性质同时成立的数字;Uim 喜欢这至少符合其中一种性质的数字;八尾勇喜欢刚好有符合其中一个性质的数字…...
产品营销方案策划/流程优化
2019独角兽企业重金招聘Python工程师标准>>> 一个开发小组的人数,少了,组没有价值,还需要付出一个leader的成本;多了,leader疲于应付,对技术leader来说就是灾难,还有当一个开发疲于应…...
wordpress 邮箱免验证/江苏营销型网站建设
索引: C# 3.0\3.5 新特性 C# 4.0 新特性 1、自动属性 以前private string lastName;public string LastName{get { return lastName; }set { lastName value; }} 现在 public string LastName{get;set;} C#编译器遇到上面空的get/set属性时,会自动在类…...
新闻网站伪原创同义词/互联网广告投放代理公司
深夜从梦中惊醒,梦中回到了老家,很多场景清晰可见,朋友家的房屋,我家的厨房。惊醒于拿着物体砸向父亲身边的墙体,结果物体反弹回来砸到了父亲的头上,砸开了一个洞。 我彻底惊醒了。 回想起以往生活中自己…...
免费照片的网站模板/网推公司
然后,就可以猥琐欲为的引用Maven仓库的jar包了。 总结:像idea这样的大公司还在用配置文件来开发软件。。。 有时候真该换种思路了。。。...
湖南省郴州市旅游景点介绍/桂林seo
pmap命令用于报告进程的内存映射关系,是Linux调试及运维一个很好的工具。语法pmap(选项)(参数)选项-x:显示扩展格式;-d:显示设备格式;-q:不显示头尾行;-V:显示指定版本。参数进程号&…...