设计模式之创建型模式

 创建型模式:创建对象的机制,从所需要实例化的对象中解耦。主要分成了五种设计模式,即工厂方法、抽象工厂、生成器、原型、单例。

文章目录

  • 工厂方法
  • 抽象工厂
  • 生成器
  • 原型
  • 单例

工厂方法

 问题:一个物流公司最初只使用卡车运输,现需要增加轮船运输业务。目前的程序代码与卡车关联。
 解决方法:定义一个用于创建对象的接口,让子类决定实例化哪一个类。FactoryMethod使一个类的实例化延迟到其子类。
在这里插入图片描述
uml类图
测试代码:

#include <iostream>
using namespace std;//产品的接口
class Transport
{
public:virtual ~Transport() {};virtual void deliver() const = 0;
};//产品A
class Truck :public Transport
{
public:void deliver() const override{std::cout << "卡车运输中ing\n";}
};//产品B
class Ship :public Transport
{
public:void deliver() const override{std::cout << "轮船运输中ing\n";}
};//创造者
class Logistics
{
public:virtual ~Logistics() {};virtual Transport* factoryMethod() const = 0;void doSomething(){Transport* transport = factoryMethod();transport->deliver();delete transport;}
};//具体的创造者A
class TruckLogistis :public Logistics {
public:virtual ~TruckLogistis() {}virtual Transport* factoryMethod() const override {return new Truck();}
};
//具体的创造者B
class ShipLogistis :public Logistics {
public:virtual ~ShipLogistis() {}virtual Transport* factoryMethod() const override {return new Ship();}
};int main()
{Logistics* truckLogistics = new TruckLogistis();Logistics* shipLogistics = new ShipLogistis();truckLogistics->doSomething();truckLogistics->doSomething();shipLogistics->doSomething();shipLogistics->doSomething();shipLogistics->doSomething();delete truckLogistics;delete shipLogistics;return 0;
}

在这里插入图片描述
缺点:应用工厂方法模式需要引入许多新的子类,代码可能会因此 变得更复杂。最好的情况是将该模式引入创建者类的现有层次结构中。

抽象工厂

 问题:家具店里有沙发、椅子、茶几等产品。产品有不同风格,如现代、北欧、工业。希望确保客户收到的产品风格统一,并可以方便的添加新产品和风格。
 解决方案:提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类。
在这里插入图片描述
uml图
测试代码:

#include <iostream>
using namespace std;class Chair
{
public:virtual~Chair() {};virtual void sitOn() const = 0;
};class ModernChair :public Chair
{
public:virtual~ModernChair() {};void sitOn() const override{std::cout << "可以被坐下的ModernChair\n";}
};class ChineseChair :public Chair
{
public:virtual~ChineseChair() {};void sitOn() const override{std::cout << "可以被坐下的ChineseChair\n";}
};class Table
{
public:virtual~Table() {};virtual void putOn() const = 0;
};class ModernTable :public Table
{
public:virtual~ModernTable() {};void putOn() const override{std::cout << "ModernTable可以放东西\n";}
};class ChineseTable :public Table
{
public:virtual~ChineseTable() {};void putOn() const override{std::cout << "ChineseTable可以放东西\n";}
};class FurnitureFacotry {//抽象工厂
public:virtual Chair* createChair() const = 0;virtual Table* createTable() const = 0;
};class ModernStyleFactory :public FurnitureFacotry {
public:Chair* createChair() const override {return new ModernChair();}Table* createTable() const override {return new ModernTable();}
};class ChineseStyleFactory :public FurnitureFacotry {
public:Chair* createChair() const override {return new ChineseChair();}Table* createTable() const override {return new ChineseTable();}
};class Client
{
private:FurnitureFacotry* m_furniturefactory;
public:Client(FurnitureFacotry* furniturefactory){setFactory(furniturefactory);}void buyFurniture(){Chair* chair = m_furniturefactory->createChair();Table* table = m_furniturefactory->createTable();chair->sitOn();table->putOn();delete chair;delete table;}void setFactory(FurnitureFacotry* furniturefactory){m_furniturefactory = furniturefactory;}
};
int main()
{ModernStyleFactory modernFactory;Client client(&modernFactory);client.buyFurniture();ChineseStyleFactory chineseFactory;client.setFactory(&chineseFactory);client.buyFurniture();return 0;
}

在这里插入图片描述
缺点:在产品族中扩展新的产品需要修改抽象工厂的接口代码。

生成器

 问题:1、构造一个房屋,需要考虑是否有车库,游泳池,花园,雕塑等,需要对诸多成员变量进行初始化工作。都写在构造函数里?每种可能都创建一个新的类?2、相同的步骤需要能够产生不同的产品,例如使用木头和玻璃盖出来的是普通住房。用黄金和水晶建造出来的是宫殿。
 解决方案:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。即将对象构造代码从产品类中抽取出来,并将其放在一个名为Builder的独立对象中。
在这里插入图片描述
uml类图
测试代码:

#include <iostream>
#include <vector>
#include <string>using namespace std;class SimpleHouse
{
public:std::vector<std::string> m_parts;void printParts() const{std::cout << "SimpleHouse 包括:\n";for (int i = 0; i < m_parts.size(); i++){std::cout << m_parts[i] << std::endl;}std::cout << "-----------------------------------\n";}
};class Builder
{
public:virtual ~Builder() {};virtual void reset() = 0;virtual void makeBaseHouse() = 0;virtual void makeGarage() = 0;virtual void makePool() = 0;
};class SimpleHouseBuilder :public Builder
{
private:SimpleHouse* m_sh;
public:SimpleHouseBuilder(){reset();}~SimpleHouseBuilder(){if (m_sh)delete m_sh;}void reset() override{m_sh = new SimpleHouse;}void makeBaseHouse() override{m_sh->m_parts.push_back("BaseHouse");}void makeGarage() override{m_sh->m_parts.push_back("Garage");}void makePool() override{m_sh->m_parts.push_back("Pool");}SimpleHouse* getResult() {SimpleHouse* result = m_sh;reset();return result;}
};
//主管:负责流程
class Director 
{
private:Builder* m_builder;
public:void setBuilder(Builder* builder){m_builder = builder;}void makeSimpleHouse() {m_builder->makeBaseHouse();m_builder->makeGarage();}void makeFullFuncHouse() {m_builder->makeBaseHouse();m_builder->makeGarage();m_builder->makePool();}
};void client(Director* director)
{std::cout << "客户自己设计流程.." << std::endl;SimpleHouseBuilder* shb = new SimpleHouseBuilder;shb->makeBaseHouse();shb->makeGarage();SimpleHouse* sh = shb->getResult();sh->printParts();delete sh;std::cout << "主管负责设计流程.." << std::endl;director->setBuilder(shb);director->makeFullFuncHouse();sh = shb->getResult();sh->printParts();delete sh;delete shb;
}int main()
{Director dir;client(&dir);return 0;
}

在这里插入图片描述
 缺点:如果产品之间的差异性很大,则不适合使用建造者模式,使用范围受到一定的限制。

原型

 问题:希望复制一个状态完全相同的对象。首先,新建一个相同类的对象。 然后,复制所有成员变量。 但是,有时候不知道具体类型,而且成员变量可能是私有的。(从外部复制对象并非总是可行的)
 解决方案:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。即复制已有对象,而无需使代码依赖他们所属的类。
在这里插入图片描述
uml类图
测试代码:

#include <iostream>
#include <unordered_map>
using namespace std;enum Type
{ROBOT_CAT = 0,ROBOT_DOG
};class Robot
{
protected:std::string m_prototype_name = "";float m_stateOfCharge = 0;
public:virtual ~Robot() {};Robot(std::string prototype_name) :m_prototype_name(prototype_name) {}virtual Robot* clone()const = 0;virtual void setStateOfCharge(float) = 0;
};class RobotCat :public Robot
{
private:float m_catValue;
public:RobotCat(std::string name,float value) :Robot(name), m_catValue(value) {}Robot* clone()const{return new RobotCat(*this);}void setStateOfCharge(float value){m_stateOfCharge = value;std::cout << "--" << m_prototype_name << " 当前电量:" << m_stateOfCharge<< ",m_CatValue:" << m_catValue << std::endl;}
};class RobotDog :public Robot
{
private:float m_dogValue;
public:RobotDog(std::string name,float value) :Robot(name), m_dogValue(value) {}Robot* clone()const{return new RobotDog(*this);}void setStateOfCharge(float value){m_stateOfCharge = value;std::cout << "--" << m_prototype_name << " 当前电量:" << m_stateOfCharge<< ",m_dogValue:" << m_dogValue << std::endl;}
};class cloneFactory
{
private:std::unordered_map<Type, Robot*> m_prototypes;
public:cloneFactory(){m_prototypes[ROBOT_CAT] = new RobotCat("机器猫", 5.0);m_prototypes[ROBOT_DOG] = new RobotCat("机器狗", 8.0);}~cloneFactory(){delete m_prototypes[ROBOT_CAT];delete m_prototypes[ROBOT_DOG];}Robot* createRobot(Type type) {return m_prototypes[type]->clone();}
};void client(cloneFactory&rf)
{std::cout << "克隆机器猫:\n";Robot* cloneRobot = rf.createRobot(ROBOT_CAT);cloneRobot->setStateOfCharge(90);delete cloneRobot;cloneRobot = rf.createRobot(ROBOT_CAT);cloneRobot->setStateOfCharge(80);delete cloneRobot;std::cout << "克隆机器狗:\n";cloneRobot = rf.createRobot(ROBOT_DOG);cloneRobot->setStateOfCharge(75);delete cloneRobot;
}int main()
{cloneFactory rf;client(rf);return 0;
}

在这里插入图片描述
缺点:克隆包含循环引用的复杂对象可能会非常麻烦。

单例

 问题:对于一些类来说,只有一个实例是很重要的。例如数据库或其共享资源的访问权限。并且这个实例需要易于被访问。
 解决方案:保证一个类只有一个实例,并提供一个访问它的全局访问点。
在这里插入图片描述

#include <iostream>
#include <thread>
#include <mutex>
using namespace std;class Singleton
{
private:Singleton(std::string value) :m_value(value) {};~Singleton() {};std::string m_value;
public:Singleton(Singleton& other) = delete;void operator=(const Singleton&) = delete;std::string value() const { return m_value; }static Singleton* getInstance(const std::string& value);
private:static Singleton* m_instance;static std::mutex m_mutex;
};std::mutex Singleton::m_mutex;
Singleton* Singleton::m_instance = nullptr;Singleton* Singleton::getInstance(const std::string& value)
{std::lock_guard<std::mutex> lock(m_mutex);if (m_instance == nullptr) {m_instance = new Singleton(value);}return m_instance;//static Singleton* instance = new Singleton(value);//return instance;
}void cat()
{Singleton* singleton = Singleton::getInstance("Cat");std::cout << singleton->value() << '\n';
}void dog()
{Singleton* singleton = Singleton::getInstance("Dog");std::cout << singleton->value() << '\n';
}int main()
{std::thread t1(cat);std::thread t2(dog);t1.join();t2.join();return 0;
}

在这里插入图片描述

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

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

相关文章

刷题之Leetcode54题(超级详细)

54. 螺旋矩阵54. 螺旋矩阵 - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/problems/spiral-matrix/submissions/521329682/ 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 示例 1&#xff1a; 输入…

SEO优化艺术:精细化技巧揭示与搜索引擎推广全面战略解读

SEO&#xff08;搜索引擎优化&#xff0c;Search Engine Optimization&#xff09;是一种网络营销策略&#xff0c;旨在通过改进网站内外的各项元素&#xff0c;提升网站在搜索引擎自然搜索结果中的排名&#xff0c;从而吸引更多目标用户访问网站&#xff0c;增加流量&#xff…

《springcloud alibaba》 四 seata安装以及使用

目录 准备调整db配置准备创建数据库 seata配置nacos配置confi.txt下载向nacos推送配置的脚本 启动seata新建项目order-seata项目 订单项目数据库脚本pom.xmlapplication.yml启动类实体类dao类service类controller类feign类mapper类 stock-seata 库存项目数据库脚本pom.xmlappli…

第⑫讲:Ceph集群OSD扩缩容中Reblanceing数据的重分布

文章目录 1.Reblanceing数据重分布的概念2.验证Reblanceing触发的过程3.Reblanceing细节4.临时关闭Reblanceing机制 1.Reblanceing数据重分布的概念 当集群中OSD进行扩缩容操作后&#xff0c;会触发一个Reblanceing数据重分布的机制&#xff0c;简单的理解就是将扩缩容前后OSD…

AAC相关知识

一、AAC音频格式种类有哪些 AAC音频格式是一种由MPEG-4标准定义的有损音频压缩格式。AAC包含两种封装格式 ADIF&#xff08;Audio Data Interchange Format音频数据交换格式&#xff09;和ADTS&#xff08;Audio Data transport Stream音频数据传输流&#xff09;。 ADIF 特点…

RFID工业读写器步骤:只需4步,即可安装使用!

高频读写器在安装的时候需要先考察清楚安装环境&#xff0c;然后根据环境要求选定读写器&#xff0c;确定好对应的安装方式&#xff0c;以及安装位置。具体操作通常包括以下几个步骤&#xff1a; 1、了解安装环境 在安装之前&#xff0c;需要了解实际应用环境&#xff0c;根据环…

鸿蒙南向开发:制作【智能儿童手表】

样例简介 本项目是基于BearPi套件开发的智能儿童手表系统&#xff0c;该系统通过与GSM模块&#xff08;型号&#xff1a;SIM808&#xff09;的通信来实现通话和定位功能。 智能儿童手表系统可以通过云和手机建立连接&#xff0c;同步时间和获取天气信息&#xff0c;通过手机下…

智慧农场物联网系统:重塑农业的未来

随着科技的进步&#xff0c;物联网技术正在逐渐改变我们的生活。在农业领域&#xff0c;物联网系统也正在发挥着越来越重要的作用&#xff0c;为智慧农场的发展提供了新的可能。本文将深入探讨智慧农场物联网系统的优势、应用场景、技术实现以及未来发展趋势。 一、智慧农场物…

npm包安装与管理:深入解析命令行工具的全方位操作指南,涵盖脚本执行与包发布流程

npm&#xff0c;全称为Node Package Manager&#xff0c;是专为JavaScript生态系统设计的软件包管理系统&#xff0c;尤其与Node.js平台紧密关联。作为Node.js的默认包管理工具&#xff0c;npm为开发者提供了便捷的方式来安装、共享、分发和管理代码模块。 npm作为JavaScript世…

CKA 基础操作教程(五)

Kubernetes Ingress 理论学习 Ingress 提供从集群外部到集群内服务的 HTTP 和 HTTPS 路由。 流量路由由 Ingress 资源所定义的规则来控制。 Ingress 资源示例&#xff1a; apiVersion: networking.k8s.io/v1 # 指定 Kubernetes 中使用的 API 版本 kind: Ingress # 指定对象…

[dvwa] CSRF

CSRF 0x01 low 跨站&#xff0c;输入密码和确认密码直接写在url中&#xff0c;将连接分享给目标&#xff0c;点击后修改密码 社工方式让目标点击短链接 伪造404页&#xff0c;在图片中写路径为payload&#xff0c;目标载入网页自动请求构造链接&#xff0c;目标被攻击 http…

吴恩达深度学习笔记:深层神经网络(Deep Neural Networks)4.5-4.8

目录 第一门课&#xff1a;神经网络和深度学习 (Neural Networks and Deep Learning)第四周&#xff1a;深层神经网络(Deep Neural Networks)4.5 为什么使用深层表示&#xff1f;&#xff08;Why deep representations?&#xff09; 第一门课&#xff1a;神经网络和深度学习 (…

设计模式之观察者模式讲解

概念&#xff1a;定义对象间一种一对多的依赖关系&#xff0c;使得当每一个对象改变状态&#xff0c;则所有依赖于它的对象都会得到通知并被自动更新。 抽象主题&#xff1a;或者叫被观察者&#xff0c;可以持有、增加、删除观察者对象。具体主题&#xff1a;实现抽象主题定义的…

一部手机游全国|打造文旅云平台,开启智慧旅游新篇章

随着移动互联网的迅猛发展&#xff0c;旅游业在不断寻求创新与变革&#xff0c;旅游小程序作为智慧文旅的一个终端&#xff0c;在智慧推荐、智慧票务、智慧导览、智慧服务、虚拟体验等方面上&#xff0c;都具备发展潜力。小程序的出现&#xff0c;则从根本上大大提升了景区智慧…

如何快速开启一个项目-ApiHug - API design Copilot

ApiHug101-001开启篇 &#x1f917; ApiHug {Postman|Swagger|Api...} 快↑ 准√ 省↓ GitHub - apihug/apihug.com: All abou the Apihug apihug.com: 有爱&#xff0c;有温度&#xff0c;有质量&#xff0c;有信任ApiHug - API design Copilot - IntelliJ IDEs Plugin |…

数据库——实验6 视图的创建与使用

1. 视图的定义 视图是根据需要以一个表或多个表为基础&#xff0c;选择满足一定条件的行或列数据的静态定义。它是一种逻辑对象&#xff0c;是一种虚拟表。视图并不生成行或列的永久副本&#xff0c;并不占用存储空 间&#xff0c;也就是说&#xff0c;视图就是保存在数据库中…

探索算力(云计算、人工智能、边缘计算等):数字时代的引擎

引言 在数字时代&#xff0c;算力是一种至关重要的资源&#xff0c;它是推动科技创新、驱动经济发展的关键引擎之一。简而言之&#xff0c;算力即计算能力&#xff0c;是计算机系统在单位时间内完成的计算任务数量或计算复杂度的度量。随着科技的不断发展和应用范围的不断扩大…

nginx到底是怎么工作的

工作流程 用户通过域名发出访问Web服务器的请求&#xff0c;该域名被DNS服务器解析为反向代理服务器的IP地址反向代理服务器接受用户的请求反向代理服务器在本地缓存中查找请求的内容&#xff0c;找到后直接把内容发送给用户如果本地缓存里没有用户所请求的信息内容&#xff0…

工地安全监测识别摄像机

工地安全监测识别摄像机是一种在建筑工地和施工现场广泛使用的智能监控设备&#xff0c;主要用于监测施工过程中可能出现的安全隐患和违规行为&#xff0c;以确保工地人员和设备的安全。通过高清摄像头、智能算法和远程监控系统的结合&#xff0c;该摄像机可以实时监测工地各个…

功能测试_验证qq账号的合法性

案例&#xff1a;验证qq账号的合法性&#xff08;要求&#xff1a;6-10位的自然数&#xff09; 使用等价类设计用例案例&#xff1a; 步骤&#xff1a; 1:明确需求&#xff1a;qq账号的合法性 2:划分等价类&#xff1a;有效等价类、有效取值、无效等价类、无效取值 3&…