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

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&#xff08;Internet Download Manager&#xff09;是一款广受好评的下载管理工具&#xff0c;其主要优势包括&#xff1a; 高速下载&#xff1a;IDM支持最大32线程的下载&#xff0c;可以显著提升下载速度1。文件分类下载&#xff1a;IDM可以根据文件后缀进行分类&#x…...

如何学习Golang语言!

第一部分&#xff1a;Go语言概述 起源与设计哲学&#xff1a;Go语言由Robert Griesemer、Rob Pike和Ken Thompson三位Google工程师设计&#xff0c;旨在解决现代编程中的一些常见问题&#xff0c;如编译速度、运行效率和并发编程。主要特点&#xff1a;Go语言的语法简单、编译…...

Redis系列之淘汰策略介绍

Redis系列之淘汰策略介绍 文章目录 为什么需要Redis淘汰策略&#xff1f;Redis淘汰策略分类Redis数据淘汰流程源码验证淘汰流程Redis中的LRU算法Redis中的LFU算法 为什么需要Redis淘汰策略&#xff1f; 由于Redis内存是有大小的&#xff0c;当内存快满的时候&#xff0c;又没有…...

sql 调优

sql 调优 SQL调优是一个复杂的过程&#xff0c;涉及多个方面&#xff0c;包括查询优化、索引优化、表结构优化等。以下是一些基本的SQL调优策略&#xff1a; 使用索引&#xff1a;确保查询中涉及的列都有适当的索引。 查询优化&#xff1a;避免使用SELECT *&#xff0c;只选取…...

【UML用户指南】-13-对高级结构建模-包

目录 1、名称 2、元素 3、可见性 4、引入与引出 用包把建模元素安排成可作为一个组来处理的较大组块。可以控制这些元素的可见性&#xff0c;使一些元素在包外是可见的&#xff0c;而另一些元素要隐藏在包内。也可以用包表示系统体系结构的不同视图。 狗窝并不复杂&#x…...

前端面试题日常练-day63 【面试题】

题目 希望这些选择题能够帮助您进行前端面试的准备&#xff0c;答案在文末 1. TypeScript中&#xff0c;以下哪个关键字用于声明一个类的构造函数&#xff1f; a) constructor b) init c) create d) initialize 2. 在TypeScript中&#xff0c;以下哪个符号用于声明可选的函…...

GAN的入门理解

这一篇主要是关于生成对抗网络的模型笔记&#xff0c;有一些简单的证明和原理&#xff0c;是根据李宏毅老师的课程整理的&#xff0c;下面有链接。本篇文章主要就是梳理基础的概念和训练过程&#xff0c;如果有什么问题的话也可以指出的。 李宏毅老师的课程链接 1.概述 GAN是…...

43【PS 作图】颜色速途

1 通过PS让画面细节模糊&#xff0c;避免被过多的颜色干扰 2 分析画面的颜色 3 作图 参考网站&#xff1a; 色感不好要怎么提升呢&#xff1f;分享一下我是怎么练习色感的&#xff01;_哔哩哔哩_bilibili https://www.bilibili.com/video/BV1h1421Z76p/?spm_id_from333.1007.…...

定个小目标之刷LeetCode热题(13)

今天来看看这道题&#xff0c;介绍两种解法 第一种动态规划&#xff0c;代码如下 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

目录 什么是提示工程&#xff08;Prompt Engineering&#xff09; Prompt 调优 Prompt 的典型构成 「定义角色」为什么有效&#xff1f; 防止 Prompt 攻击 攻击方式 1&#xff1a;著名的「奶奶漏洞」 攻击方式 2&#xff1a;Prompt 注入 防范措施 1&#xff1a;Prompt 注…...

centos安装vscode的教程

centos安装vscode的教程 步骤一&#xff1a;打开vscode官网找到历史版本 历史版本链接 步骤二&#xff1a;找到文件下载的位置 在命令行中输入&#xff08;稍等片刻即可打开&#xff09;&#xff1a; /usr/share/code/bin/code关闭vscode后&#xff0c;可在应用程序----编程…...

面试题------>MySQL!!!

一、连接查询 ①&#xff1a;左连接left join &#xff08;小表在左&#xff0c;大表在右&#xff09; ②&#xff1a;右连接right join&#xff08;小表在右&#xff0c;大表在左&#xff09; 二、聚合函数 SQL 中提供的聚合函数可以用来统计、求和、求最值等等 COUNT&…...

英伟达:史上最牛一笔天使投资

200万美元的天使投资&#xff0c;让刚成立就面临倒闭风险的英伟达由危转安&#xff0c;并由此缔造了一个2.8万亿美元的市值神话。 这是全球风投史上浓墨重彩的一笔。 前不久&#xff0c;黄仁勋在母校斯坦福大学的演讲中&#xff0c;提到了人生中的第一笔融资——1993年&#x…...

PDF分页处理:技术与实践

引言 在数字化办公和学习中&#xff0c;PDF文件因其便携性和格式稳定性而广受欢迎。然而&#xff0c;处理大型PDF文件时&#xff0c;我们经常需要将其拆分成单独的页面&#xff0c;以便于管理和分享。本文将探讨如何使用Python编程语言和一些流行的库来实现PDF文件的分页处理。…...

数据可视化——pyecharts库绘图

目录 官方文档 使用说明&#xff1a; 点击基本图表 可以点击你想要的图表 安装&#xff1a; 一些例图&#xff1a; 柱状图&#xff1a; 效果&#xff1a; 折线图&#xff1a; 效果&#xff1a; 环形图&#xff1a; 效果&#xff1a; 南丁格尔图&#xff08;玫瑰图&am…...

Python的return和yield,哪个是你的菜?

目录 1、return基础介绍 &#x1f4da; 1.1 return用途&#xff1a;数据返回 1.2 return执行&#xff1a;函数终止 1.3 return深入&#xff1a;无返回值情况 2、yield核心概念 &#x1f347; 2.1 yield与迭代器 2.2 生成器函数构建 2.3 yield的暂停与续行特性 3、retur…...

持续总结中!2024年面试必问 20 道分布式、微服务面试题(七)

上一篇地址&#xff1a;持续总结中&#xff01;2024年面试必问 20 道分布式、微服务面试题&#xff08;六&#xff09;-CSDN博客 十三、请解释什么是服务网格&#xff08;Service Mesh&#xff09;&#xff1f; 服务网格&#xff08;Service Mesh&#xff09;是一种用于处理服…...

AJAX 跨域

这里写目录标题 同源策略JSONPJSONP 是怎么工作的JSONP 的使用原生JSONP实践CORS 同源策略 同源&#xff1a; 协议、域名、端口号 必须完全相同、 当然网页的URL和AJAX请求的目标资源的URL两者之间的协议、域名、端口号必须完全相同。 AJAX是默认遵循同源策略的&#xff0c;不…...

3 数据类型、运算符与表达式-3.1 C语言的数据类型和3.2 常量与变量

数据类型 基本类型 整型字符型实型(浮点型) 单精度型双精度型 枚举类型 构造类型 数组类型结构体类型共用体类型 指针类型空类型 #include <stdio.h> #include <string.h> #include <stdbool.h> // 包含布尔类型定义 // 常量和符号常量 #define PRICE 30//…...

应用升级/灾备测试时使用guarantee 闪回点迅速回退

1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间&#xff0c; 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点&#xff0c;不需要开启数据库闪回。…...

.Net框架,除了EF还有很多很多......

文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

【入坑系列】TiDB 强制索引在不同库下不生效问题

文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

学校招生小程序源码介绍

基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码&#xff0c;专为学校招生场景量身打造&#xff0c;功能实用且操作便捷。 从技术架构来看&#xff0c;ThinkPHP提供稳定可靠的后台服务&#xff0c;FastAdmin加速开发流程&#xff0c;UniApp则保障小程序在多端有良好的兼…...

macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用

文章目录 问题现象问题原因解决办法 问题现象 macOS启动台&#xff08;Launchpad&#xff09;多出来了&#xff1a;Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显&#xff0c;都是Google家的办公全家桶。这些应用并不是通过独立安装的…...

如何在看板中有效管理突发紧急任务

在看板中有效管理突发紧急任务需要&#xff1a;设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP&#xff08;Work-in-Progress&#xff09;弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中&#xff0c;设立专门的紧急任务通道尤为重要&#xff0c;这能…...

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样…...

ardupilot 开发环境eclipse 中import 缺少C++

目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)

在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

06 Deep learning神经网络编程基础 激活函数 --吴恩达

深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...