【C++】设计模式:建造者、原型、单例

😏★,°:.☆( ̄▽ ̄)/$:.°★ 😏
这篇文章主要介绍设计模式:建造者、原型、单例。
学其所用,用其所学。——梁启超
欢迎来到我的博客,一起学习,共同进步。
喜欢的朋友可以关注一下,下次更新不迷路🥞

文章目录

    • :smirk:1. 建造者模式
    • :blush:2. 原型模式
    • :satisfied:3. 单例模式

😏1. 建造者模式

建造者模式:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

建造者模式的结构包含以下几个角色:

  • 抽象建造者(AbstractBuilder):创建一个Product对象的各个部件指定的抽象接口;
  • 具体建造者(ConcreteBuilder):实现AbstractBuilder的接口,实现各个部件的具体构造方法和装配方法,并返回创建结果。
  • 产品(Product):具体的产品对象
  • 指挥者(Director): 构建一个使用Builder接口的对象,安排复杂对象的构建过程,客户端一般只需要与Director交互,指定建造者类型,然后通过构造函数或者setter方法将具体建造者对象传入Director。它主要作用是:隔离客户与对象的生产过程,并负责控制产品对象的生产过程
#include <iostream>
#include <string>

// 产品类
class Product {
public:
    void setPartA(const std::string& partA) {
        partA_ = partA;
    }

    void setPartB(const std::string& partB) {
        partB_ = partB;
    }

    void setPartC(const std::string& partC) {
        partC_ = partC;
    }

    void show() {
        std::cout << "Product parts: " << partA_ << ", " << partB_ << ", " << partC_ << std::endl;
    }

private:
    std::string partA_;
    std::string partB_;
    std::string partC_;
};

// 抽象建造者类
class Builder {
public:
    virtual void buildPartA() = 0;
    virtual void buildPartB() = 0;
    virtual void buildPartC() = 0;
    virtual Product* getProduct() = 0;
};

// 具体建造者类 A
class ConcreteBuilderA : public Builder {
public:
    void buildPartA() override {
        product_->setPartA("PartA of Product A");
    }

    void buildPartB() override {
        product_->setPartB("PartB of Product A");
    }

    void buildPartC() override {
        product_->setPartC("PartC of Product A");
    }

    Product* getProduct() override {
        return product_;
    }

private:
    Product* product_ = new Product();
};

// 指挥者类
class Director {
public:
    void construct(Builder* builder) {
        builder->buildPartA();
        builder->buildPartB();
        builder->buildPartC();
    }
};

int main() {
    Director director;

    ConcreteBuilderA builderA;
    director.construct(&builderA);

    Product* productA = builderA.getProduct();
    productA->show();

    delete productA;

    return 0;
}

适用环境:

  • 需要生成的产品对象有复杂的内部结构(通常包含多个成员变量);
  • 产品对象内部属性有一定的生成顺序;
  • 同一个创建流程适用于多种不同的产品。

😊2. 原型模式

原型模式:使用原型实例指定待创建对象的类型,并且通过复制这个原型来创建新的对象。

原型式的结构包含以下几个角色:

  • 抽象原型类(AbstractPrototype):声明克隆clone自身的接口
  • 具体原型类(ConcretePrototype):实现clone接口
  • 客户端(Client):客户端中声明一个抽象原型类,根据客户需求clone具体原型类对象实例

原型模式可以说是“复制”,即克隆,但这个复制不是代码的复制,而是将对象包含的所有属性都创建一份拷贝。但不同的复制操作,可能会产生两种不同的拷贝,即浅拷贝和深拷贝。

#include <iostream>

// 原型基类
class Prototype {
public:
    virtual Prototype* clone() = 0;
    virtual void show() = 0;
};

// 具体原型类 A
class ConcretePrototypeA : public Prototype {
public:
    Prototype* clone() override {
        return new ConcretePrototypeA(*this);
    }

    void show() override {
        std::cout << "ConcretePrototypeA" << std::endl;
    }
};

// 具体原型类 B
class ConcretePrototypeB : public Prototype {
public:
    Prototype* clone() override {
        return new ConcretePrototypeB(*this);
    }

    void show() override {
        std::cout << "ConcretePrototypeB" << std::endl;
    }
};

int main() {
    ConcretePrototypeA prototypeA;
    Prototype* clonedA = prototypeA.clone();
    clonedA->show();
    delete clonedA;

    ConcretePrototypeB prototypeB;
    Prototype* clonedB = prototypeB.clone();
    clonedB->show();
    delete clonedB;

    return 0;
}

适用环境:

  • 当创建新的对象实例较为复杂时,原型模式可以简化创建过程;
  • 需要避免使用分层次的工厂类来创建分层次的对象,并且类的实例对象只有一个或很少几个的组合状态,通过复制原型对象得到新实例,比通过使用构造函数创建一个新实例会更加方便。

😆3. 单例模式

单例模式是指在整个系统生命周期内,保证一个类只能产生一个实例,确保该类的唯一性。

单例模式可以保证线程安全,即给共享的资源加把锁,保证每个资源变量每时每刻至多被一个线程占用。

单例模式可以分为懒汉式和饿汉式,两者之间的区别在于创建实例的时间不同。懒汉式只有使用时才会创建实例,这种情况要考虑线程安全;饿汉式初始化就会创建实例,需要时直接调用,不用考虑安全问题。

饿汉式实现:

头文件:

// 饿汉实现 /
class Singleton
{
public:
    // 获取单实例
    static Singleton* GetInstance();

    // 释放单实例,进程退出时调用
    static void deleteInstance();

    // 打印实例地址
    void Print();

private:
    // 将其构造和析构成为私有的, 禁止外部构造和析构
    Singleton();
    ~Singleton();

    // 将其拷贝构造和赋值构造成为私有函数, 禁止外部拷贝和赋值
    Singleton(const Singleton &signal);
    const Singleton &operator=(const Singleton &signal);

private:
    // 唯一单实例对象指针
    static Singleton *g_pSingleton;
};

源文件:

// 代码一运行就初始化创建实例 ,本身就线程安全
Singleton* Singleton::g_pSingleton = new (std::nothrow) Singleton();

Singleton* Singleton::GetInstance()
{
    return g_pSingleton;
}

void Singleton::deleteInstance()
{
    if (g_pSingleton)
    {
        delete g_pSingleton;
        g_pSingleton = nullptr;
    }
}

void Singleton::Print()
{
    std::cout << "我的实例内存地址是:" << this << std::endl;
}

Singleton::Singleton()
{
    std::cout << "构造函数" << std::endl;
}

Singleton::~Singleton()
{
    std::cout << "析构函数" << std::endl;
}

main程序:

#include <iostream>
#include <memory>
#include <mutex>

class Singleton {
public:
    static std::shared_ptr<Singleton> getSingleton();

    void print() {
        std::cout << "Hello World." << std::endl;
    }

    ~Singleton() {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
    }

private:
    Singleton() {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
    }
};

static std::shared_ptr<Singleton> singleton = nullptr;
static std::once_flag singletonFlag;

std::shared_ptr<Singleton> Singleton::getSingleton() {
    std::call_once(singletonFlag, [&] {
        singleton = std::shared_ptr<Singleton>(new Singleton());
    });
    return singleton;
}

请添加图片描述

以上。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

接口自动化测试用例的编写方法

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 关注公众号【互联网杂货铺】&#xff0c;回复 1 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 phpunit 接口自动化测试系列 Post接口自动化测试用例 Post方式…

Java使用spire.doc操作word文档(合并、插入文字图片和表格、替换书签)

一、引入依赖 <dependency><groupId>e-iceblue</groupId><artifactId>spire.office</artifactId><version>7.5.4</version> </dependency> 二、word操作 1、合并word文档 import com.spire.doc.Document; import com.spir…

java多线程实现同步的方式介绍

在 Java 多线程编程中&#xff0c;同步是确保多个线程在访问共享资源时的正确性和一致性的重要机制。Java 提供了多种方式来实现线程同步&#xff0c;每种方式都有其特点和适用场景。以下是一些常见的同步方式及其特点和应用场景&#xff0c;以及简单的例子来说明它们的用法。 …

从零开始的LeetCode刷题日记:142.环形链表II

一.相关链接 视频链接&#xff1a;代码随想录&#xff1a;142.环形链表II 题目链接&#xff1a;142.环形链表II 二.心得体会 这道题是一道链表题&#xff0c;但他没有对头结点的操作&#xff0c;所以不用虚拟头结点。这道题要分两步进行&#xff0c;第一步是判断链表有没有环…

win11修改主机mac地址

很多时候&#xff0c;为了限制恶意的蹭流浪&#xff0c;除了分配固定的ip地址外&#xff0c;还限制mac地址。只有mac与ip一致&#xff0c;才能上网冲浪 网络适配器中修改 搜索“控制面板”打开 控制面板 > 网络和Internet > 网络和共享中心 >查看网络状态和任务>…

Redis什么这么快和Redis单线程模型和多线程

概述 1、完全基于内存&#xff0c;绝大部分请求是纯粹的内存操作&#xff0c;非常快速。数据存在内存中&#xff0c;类似于HashMap&#xff0c;HashMap的优势就是查找和操作的时间复杂度都是O(1)&#xff1b; 2、数据结构简单&#xff0c;对数据操作也简单&#xff0c;Redis中…

测试常用的Linux命令

前言 直接操作硬件 将把操作硬件的代码封装成系统调用&#xff0c;供程序员使用 虚拟机软件 可以模拟的具有完整硬件系统的功能 可以在虚拟机上安装不同的操作系统 Linux内核只有一个&#xff0c;发行版有很多种 内核来运行程序和管理像磁盘和打印机等硬件设备的核心程序 终端…

AD20中关于“Net(s) Not Found in Differential Pair”的解决方法

问题描述&#xff1a; Net(s) Not Found in Differential Pair&#xff1a;在差分对中找不到网络 我们需要在原理图设计中需要添加差分对&#xff0c;已经遵循了_N _P 结尾&#xff0c;也添加了差分对标识符&#xff0c;但是转换到PCB时显示差分对报错 解决方法&#xf…

GSA、GSEA、ssGSEA、GSVA用到的统计学知识点

文章目录 概率密度函数&#xff08;probability density function&#xff0c;PDF&#xff09;分布函数&#xff08;Cumulative Distribution Function&#xff0c;CDF&#xff09;核密度估计&#xff08;KDE&#xff09;经验累计分布函数&#xff08;Empirical Cumulative Dis…

VUE_nuxt启动只能通过localhost访问,ip访问不到:问题解决

修改项目根目录下的 package.json "config": {"nuxt": {"host": "0.0.0.0","port": "3000"} } 这样项目启动后就可以通过ip进行访问了

目标检测论文模型笔记——YOLO系列

1. YOLOv1的核心思想&#xff1a; YOLOv1&#xff1a;使用整张图作为输入&#xff0c;直接在输出层回归bounding box和类别&#xff1b;&#xff08;one-stage&#xff09;Faster RCNN&#xff1a;使用用整张图作为输入&#xff0c;但整体采用了RCNN&#xff1a; proposalclas…

Facebook的社交未来:元宇宙时代的数字共融

引言&#xff1a; 随着科技的不断进步和社会的快速发展&#xff0c;人们对于社交网络的需求和期待也在不断演变。在这个数字化时代&#xff0c;元宇宙的概念逐渐引发了人们对社交体验的重新思考。作为全球最大的社交网络之一&#xff0c;Facebook正在积极探索元宇宙时代的社交…

低空经济20人|卓翼智能任雪峰:以技术驱动市场,引领无人机细分领域创新

作为国内系留无人机领域的领头羊企业&#xff0c;卓翼智能致力于提供智能无人系统解决方案。本期“低空经济20人”请到卓翼智能CEO任雪峰分享他对系留无人机研发应用的经验以及未来无人机行业生态发展的观点。 如今&#xff0c;无人机的应用场景逐渐广泛&#xff0c;在社会发展…

go go.mod file not found in current directory or any parent directory

场景&#xff1a; 安装好 liteide 之后创建了第一个 “hello world” 的golang 项目&#xff0c;却报了如下错误。 原因分析&#xff1a; go 的环境配置问题。与 golang 的包管理有关。 解决方案&#xff1a; 如果你是 Windows 系统&#xff0c;快捷键 “WinR”&#xff0c…

Baumer工业相机堡盟工业相机如何通过NEOAPI SDK实现双快门采集两张曝光时间非常短的图像(C#)

Baumer工业相机堡盟工业相机如何通过NEOAPI SDK实现双快门采集两张曝光时间非常短的图像&#xff08;C#&#xff09; Baumer工业相机Baumer工业相机定序器功能的技术背景Baumer工业相机通过NEOAPI SDK使用定序器功能预期的相机动作技术限制定序器的工作原理 Baumer工业相机通过…

获取C语言语句对应的汇编码和机器指令

借助IDE的调试功能 以CodeBlocks为例&#xff0c;先设置断点&#xff0c;然后点击红色三角形调试。 然后选择Debug➡ Debugging Windows➡Disassembly 就可以看到了 使用命令行 在工程文件中&#xff0c;一般可以找到一个.o文件。如果没有&#xff0c;可以先在program.c的目录下…

【JavaEE初阶】 关于JVM垃圾回收

文章目录 &#x1f343;前言&#x1f38b;死亡对象的判断算法&#x1f6a9;引用计数算法&#x1f6a9;可达性分析算法 &#x1f333;垃圾回收算法&#x1f6a9;标记-清除算法&#x1f6a9;复制算法&#x1f6a9;标记-整理算法&#x1f6a9;分代算法&#x1f388;哪些对象会进入…

在哪里可以下载大自然短视频素材?大自然短视频素材网分享

如果你想要制作短视频但又担心找不到那些让人心旷神怡的大自然素材&#xff0c;别急&#xff0c;我这就给你安利几个可以下载到高清、无水印的大自然短视频素材的网站。这样&#xff0c;你不仅能让作品视觉效果大大提升&#xff0c;还能让观众感受到大自然的魅力&#xff0c;一…

C语言之指针习题一

1. 解析&#xff1a;全选 2. 解析&#xff1a;A.当内存空间释放后&#xff0c;指针将指向其他的区域&#xff0c;成为野指针 3. 解析&#xff1a;B&#xff0c;assert只会在调试模式&#xff08;debug&#xff09;下使用&#xff0c;release不会使用 4. 解析&#xff1a; A…

【CSP试题回顾】202109-1-数组推导

CSP-202109-1-数组推导 解题代码 #include<iostream> #include<vector> #include<algorithm> using namespace std;long long maxSum, minSum;int main() { int n;cin >> n;vector<int>B(n);for (auto& it : B){cin >> it;maxSum …