C++设计模式笔记(内附可运行代码示例)

news2024/11/27 20:28:31

持续更新, 欢迎关注.......

前言

设计目的

高内聚,低耦合

设计原则

1、开放封闭原则

类的改动是通过增加代码进行,而不是修改源代码。

2、单一职责原则

职责单一,对外只提供一种功能,引起类变化的原因都应该只有一个。

3、依赖倒置原则

依赖于抽象,不要依赖于具体实现,也就是针对接口编程。

4、接口隔离原则

一个接口应该只提供一种对外功能,不应该把所有操作都封装到一个接口中。

5、里氏替换原则

任何抽象类出现的地方都可以用他的实现类进行替换。实际就是虚拟机制,语言级别实现面向对象功能。

6、优先使用组合而不是继承

7、迪米特法则

一个对象应该对其他对象尽可能少的了解,从而降低各个对象之间的耦合。

UML类图

参考UML类图几种关系的总结_在类图中,类与类-CSDN博客

创建型模式

单例模式

场景

- 在多个线程之间, 比如初始化一次 socket 资源; 比如 servlet 环境, 共享同一个资源或者
操作同一个对象

- 在整个程序空间使用全局变量, 共享资源
- 大规模系统中, 为了性能的考虑, 需要节省对象的创建时间等等。

核心要点

a) 构造函数私有化
b) 提供一个全局的静态方法(全局访问点)
c) 在类中定义一个静态指针, 指向本类的变量的静态变量指针

示例

懒汉式

构造延时到使用Instance时

#include <iostream>
using namespace std;
//懒汉式
class Singelton {
private:
    Singelton()
    {
        m_singer = NULL;
        m_count = 0;
        cout << "构造函数 Singelton ... do" << endl;
    }
public:
    static Singelton *getInstance()
    {
        if (m_singer == NULL ) //懒汉式: 1 每次获取实例都要判断 2 多线程会有问题
        {
            m_singer = new Singelton;
        }
        return m_singer;
    }

    static void printT()
    {
        cout << "m_count: " << m_count << endl;
    }
private:
    static Singelton *m_singer;
    static int m_count;
};

Singelton *Singelton::m_singer = NULL; //懒汉式 并没有创建单例对象
int Singelton::m_count = 0;

int main()
{
    cout << "演示 懒汉式" << endl;
    Singelton *p1 = Singelton::getInstance(); //只有在使用的时候, 才去创建对象。
    Singelton *p2 = Singelton::getInstance();
    if (p1 != p2) {
        cout << "不是同一个对象" << endl;
    } else {
        cout << "是同一个对象" << endl;
    }
    p1->printT();
    p2->printT();
    return 0;
}

运行结果:

演示 懒汉式
构造函数 Singelton ... do
是同一个对象
m_count: 0
m_count: 0
饿汉式

直接编译时就构造

#include <iostream>
using namespace std;

class Singelton2
{

private:
    Singelton2()
    {
        m_singer = NULL;
        m_count = 0;
        cout << "构造函数 Singelton ... do" << endl;
    }

public:
    static Singelton2 *getInstance()
    {
        // if (m_singer == NULL )
        // {
            // m_singer = new Singelton2;
        // }
        return m_singer;
    }
    static void FreeInstance()
    {
        if (m_singer != NULL)
        {
            delete m_singer;
            m_singer = NULL;
            m_count = 0;
        }
    }
    static void printT()
    {
        cout << "m_count: " << m_count << endl;
    }
private:
    static Singelton2 *m_singer;
    static int m_count;
};

Singelton2 *Singelton2::m_singer = new Singelton2; //不管你创建不创建实例, 均把实例 new出来
int Singelton2::m_count = 0;

int main()
{
    cout << "演示 饿汉式" << endl;
    Singelton2 *p1 = Singelton2::getInstance(); //只有在使用的时候, 才去创建对象。
    Singelton2 *p2 = Singelton2::getInstance();
    if (p1 != p2) {
        cout << "不是同一个对象" << endl;
    } else {
        cout << "是同一个对象" << endl;
    }
    p1->printT();
    p2->printT();
    Singelton2::FreeInstance();
    Singelton2::FreeInstance();
    return 0;
}

运行结果:

构造函数 Singelton ... do
演示 饿汉式
是同一个对象
m_count: 0
m_count: 0

简单工厂模式

场景

核心

1、工厂角色 --负责创建所有实例

工厂类是整个模式的关键,需要包含判断逻辑,能够根据外界给定的信息,决定创建哪个具体类的对象

2、抽象角色 --创建的所有对象的父类

3、具体产品角色 --具体实例对象

示例

工厂类里一定有选择逻辑

#include <iostream>
#include <cstring>
using namespace std;
//思想: 核心思想是用一个工厂, 来根据输入的条件产生不同的类, 然后根据不同类的 virtual函数得到不同的结果。
//元素分析:
//抽象产品类: 水果类
//具体的水果类: 香蕉类、 苹果类、 梨子
//优点 适用于不同情况创建不同的类时
//缺点 客户端必须要知道基类和工厂类, 耦合性差 增加一个产品, 需要修改工厂类
class Fruit {
public:
    virtual void getFruit() = 0;
protected:
private:
};

class Banana : public Fruit {
public:
    virtual void getFruit()
    {
        cout<<"香蕉"<<endl;
    }
protected:
private:
};

class Pear : public Fruit {
public:
    virtual void getFruit()
    {
        cout<<"梨子"<<endl;
    }
protected:
private:
};

class Factory
{
public:
    static Fruit* Create(char *name)
    {
        Fruit *tmp = NULL;
        if (strcmp(name, "pear") == 0)
        {
            tmp = new Pear();
        } else if (strcmp(name, "banana") == 0) {
            tmp = new Banana();
        } else {
            return NULL;
        }
        return tmp;
    }
protected:
private:
};

int main() {
    Fruit *pear = Factory::Create("pear");
    if (pear == NULL) {
        cout << "创建 pear 失败\n";
    }
    pear->getFruit();
    Fruit *banana = Factory::Create("banana");
    banana->getFruit();
    return 0;
}

 运行结果

梨子
香蕉

 工厂模式

场景

核心

1、抽象工厂(Creator) 角色                                                                                                  ---工厂方法模式的核心, 任何工厂类都必须实现这个接口。
2、具体工厂( Concrete Creator) 角色
---具体工厂类是抽象工厂的一个实现, 负责实例化产品对象。
3、抽象(Product) 角色
---工厂方法模式所创建的所有对象的父类, 它负责描述所有实例所共有的公共接口。
4、具体产品(Concrete Product) 角色
---工厂方法模式所创建的具体实例对象

和简单工厂模式不同:

a) 多了个抽象工厂类,每个具体工厂类统一来自抽象工厂

b) 添加新的产品对象时,只需添加一个具体对象和一个具体工厂

示例

1、抽象工厂:FruitFactory,具体工厂:BananaFactory、AppleFactory

2、抽象产品:Fruit,具体产品:Banana、Apple

3、main函数调用具体工厂时只是先把具体工厂创建出来,然后通过工厂的GetFruit创建具体对象

#include "iostream"
using namespace std;

class Fruit
{
public:
    virtual void sayname()
    {
        cout<<"fruit\n";
    }
};

class FruitFactory
{
public:
    virtual Fruit* getFruit()
    {
        return new Fruit();
    }
};
//香蕉
class Banana : public Fruit
{
public:
    virtual void sayname()
    {
        cout<<"Banana \n"<<endl;
    }
};
//香蕉工厂
class BananaFactory : public FruitFactory
{
public:
    virtual Fruit* getFruit()
    {
        return new Banana;
    }
};

//苹果
class Apple : public Fruit
{
public:
    virtual void sayname()
    {
        cout<<"Apple \n"<<endl;
    }
};

//苹果工厂
class AppleFactory : public FruitFactory
{
public:
    virtual Fruit* getFruit()
    {
        return new Apple;
    }
};

int main()
{
    FruitFactory * ff = NULL;
    Fruit *fruit = NULL;
    //1 香蕉
    ff = new BananaFactory(); // 1、先创建具体工厂
    fruit = ff->getFruit(); // 2、通过具体工厂创建具体对象
    fruit->sayname();
    delete fruit;
    delete ff;
    //2 苹果
    ff = new AppleFactory();
    fruit = ff->getFruit();
    fruit->sayname();
    delete fruit;
    delete ff;
    cout<<"hello....\n";
    return 0;
}

运行结果:

Banana 

Apple 

hello....

抽象工厂模式

场景

可以一下生产一个产品族

核心

注意:上图的ConcreteFactory存在漏画问题,应该是CreateProductA(): AbStractProductA 和 CreateProductB(): AbStractProductB

1、抽象工厂角色

2、具体工厂角色

3、抽象产品角色

4、具体产品角色

示例

抽象工厂类:FruitFactory,具体工厂类:NorthFruitFactory、SourthFruitFactory;

抽象产品类:Fruit,具体产品类:SouthBanana/SouthApple/NorthBanana/NorthApple。

GetFruit切换成了GetApple、GetBanana,所以可以建立产品族。

#include "iostream"
using namespace std;

class Fruit
{
public:
    virtual void sayname()
    {
        cout<<"fruit\n";
    }
};

class FruitFactory
{
public:
    virtual Fruit* getApple()
    {
        return new Fruit();
    }
    virtual Fruit* getBanana()
    {
        return new Fruit();
    }
};
//南方香蕉
class SouthBanana : public Fruit
{
public:
    virtual void sayname()
    {
        cout<<"South Banana \n"<<endl;
    }
};

//南方苹果
class SouthApple : public Fruit
{
public:
    virtual void sayname() {
        cout << "South Apple \n" << endl;
    }
};

//北方香蕉
class NorthBanana : public Fruit
{
public:
    virtual void sayname()
    {
        cout<<"North Banana \n"<<endl;
    }
};

//北方苹果
class NorthApple : public Fruit
{
public:
    virtual void sayname()
    {
        cout<<"North Apple \n"<<endl;
    }
};

class SourthFruitFactory : public FruitFactory
{
public:
    virtual Fruit* getApple()
    {
        return new SouthApple();
    }
    virtual Fruit* getBanana()
    {
        return new SouthBanana();
    }
};
class NorthFruitFactory : public FruitFactory
{
public:
    virtual Fruit* getApple()
    {
        return new NorthApple();
    }
    virtual Fruit* getBanana()
    {
        return new NorthBanana();
    }
};
int main()
{
    FruitFactory * ff = NULL;
    Fruit *fruit = NULL;
    ff = new SourthFruitFactory(); // 1、建个南方工厂
    fruit = ff->getApple();        // 2、建立南方苹果
    fruit->sayname();
    fruit = ff->getBanana();       // 3、建立南方香蕉
    fruit->sayname();
    delete fruit;
    delete ff;
    ff = new NorthFruitFactory();
    fruit = ff->getApple();
    fruit->sayname();
    fruit = ff->getBanana();
    fruit->sayname();
    delete fruit;
    delete ff;
    cout<<"hello....\n";
    return 0;
}

运行结果

South Apple 

South Banana 

North Apple 

North Banana 

hello....

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

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

相关文章

【中项】系统集成项目管理工程师-第9章 项目管理概论-9.1PMBOK的发展与9.2项目基本要素

前言&#xff1a;系统集成项目管理工程师专业&#xff0c;现分享一些教材知识点。觉得文章还不错的喜欢点赞收藏的同时帮忙点点关注。 软考同样是国家人社部和工信部组织的国家级考试&#xff0c;全称为“全国计算机与软件专业技术资格&#xff08;水平&#xff09;考试”&…

数据库设计效率提高的5大注意事项

数据库设计效率和质量的提高对项目影响深远&#xff0c;能够显著提升数据访问速度&#xff0c;确保数据一致性和完整性&#xff0c;减少应用开发和维护成本&#xff0c;同时提升系统稳定性和用户体验。如果数据库设计不佳会导致项目性能低下&#xff0c;数据访问缓慢&#xff0…

Java7.0标准之重要特性及用法实例(十八)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 新书发布&#xff1a;《Android系统多媒体进阶实战》&#x1f680; 优质专栏&#xff1a; Audio工程师进阶系列…

APDL(ANSYS Parametric Design Language)初识

APDL&#xff08;ANSYS Parametric Design Language&#xff09;编写涉及使用ANSYS的参数化设计语言来创建、修改和执行有限元分析&#xff08;FEA&#xff09;任务。以下是一些关于APDL编写的基本步骤、技巧和示例&#xff1a; 一、基本步骤 了解APDL基础&#xff1a; 熟悉AP…

并发--快速查询死锁信息

使用jstack查看线程堆栈信息 jstack&#xff1a;jdk提供的一个工具&#xff0c;可以查看java进程中线程堆栈信息。 位于&#xff1a;jdk1.8.0_121\bin包下 死锁代码 public class DeadLockDemo {private static String A "A";private static String B "B"…

视频平台麓战奥运经济,谁能接住这“破天的富贵”?

文丨郭梦仪 与巴黎奥运会炸裂开幕式的“松弛感”不同&#xff0c;赛场外的流量之争早已硝烟弥漫。 今年&#xff0c;腾讯、咪咕、快手、抖音与中央广播电视总台达成奥运转播版权合作&#xff0c;长短视频平台各占一半。 而今&#xff0c;获得转播权的视频平台们&#xff0c;…

20240731 每日AI必读资讯

&#x1f4f1;苹果AI版iOS首日火爆&#xff1a;聊天秒变高情商&#xff0c;大模型成最强嘴替&#xff0c;Siri华丽变身 - 苹果的Apple Intelligence终于面世&#xff01;随着iOS 18.1 Beta版的上线&#xff0c;注册开发者从即日起就能体验到苹果AI的部分功能。 - Siri的全面换…

出行方案,智能推荐:用友BIP商旅云6.0推出AI新装备

随着企业业务的不断拓展和员工出行需求的日益复杂化&#xff0c;传统的商旅预订方式已经难以应对&#xff0c;同时企业在商旅成本控制方面也面临着巨大的挑战。为此用友BIP商旅云6.0推出了创新性的AI新装备——智能推荐&#xff0c;以智能分析与精准预测&#xff0c;为企业提供…

基于springboot的大学奖学金评定管理系统表结构调试讲解源码

基于springboot的大学奖学金评定管理系统 赠送自己录的运行教程视频&#xff0c;无经验也可以运行起来。 提供远程调试服务&#xff0c;加钱可远程帮忙运行起来。 项目功能: 二、项目功能介绍 管理员 个人中心&#xff1a;这是管理员的个人工作区域&#xff0c;允许管理员…

vue基础3

1.推荐好用的第三方框架 BootCDN - Bootstrap 中文网开源项目免费 CDN 加速服务 1.moment.js 2.dayjs 2.收集表达数据 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><title>Document</title><…

MSYS2下载安装和使用

Minimalist GNU&#xff08;POSIX&#xff09;system on Windows&#xff0c;Windows下的GNU环境。 目录 1. 安装 2. pacman命令 3. 配置vim 4. 一些使用示例 4.1 编译代码 4.2 SSH登录远程服务器 1. 安装 官网下载&#xff1a;https://www.msys2.org/ 双击.exe文件&am…

【python】OpenCV—Faster Video File FPS

文章目录 1、需求描述2、正常方法 cv2.read3、加速方法 imutils.video.FileVideoStream4、涉及到的核心库函数4.1、imutils.video.FPS4.2、imutils.video.FileVideoStream 5、参考 1、需求描述 使用线程和队列数据结构将视频文件的 FPS 速率提高 &#xff01; 我们的目标是将…

解决Qt3D程序场景中无法显示创建的立体图形?

有的新手在创建Qt3D程序时&#xff0c;因为不熟练&#xff0c;导致经常遇到无法显示3D图形的情况。 原因其实也简单&#xff0c;就是设置的摄像机的位置不对&#xff0c;或者压根没有设置摄像机。 // CameraQt3DRender::QCamera *cameraEntity view.camera();cameraEntity-&g…

文件未保存后能否恢复?分享实用恢复指南,6个方法

在日常用电脑时文件未保存而导致的数据丢失&#xff0c;是许多人都会遭遇的棘手问题。那么面对这样的情况&#xff0c;文件真的能够恢复吗&#xff1f;本文将深入分析文件恢复的可能性&#xff0c;并提供一系列实用的建议。 一、了解文件恢复的基础 首先我们需要明白文件恢复并…

每一次新建终端固定到某个环境,配置PyCharm终端以自动激活环境

在PyCharm中&#xff0c;即使已经为项目设置了特定的Python解释器&#xff0c;默认情况下&#xff0c;新建的终端可能不会自动激活与项目绑定的Conda虚拟环境。要解决这个问题&#xff0c;可以采取以下步骤&#xff1a; 1. 配置PyCharm终端以自动激活环境 PyCharm支持为每个项…

手把手教你用家用电脑完成图片和视频AI去水印功能

一.效果展示 二.video-subtitle-remover源码地址 soda151314/video-subtitle-remover: 基于AI的图片/视频硬字幕去除、文本水印去除&#xff0c;无损分辨率生成去字幕、去水印后的图片/视频文件。无需申请第三方API&#xff0c;本地实现。AI-based tool for removing hard-cod…

孟德尔随机化、R语言,报错,如何解决?

&#x1f3c6;本文收录于《CSDN问答解惑-专业版》专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收…

推荐一款前端滑动验证码插件(Vue、uniapp)

uniapp版本&#xff1a;滑块拼图验证码&#xff0c;有后端&#xff0c;简单几步即可实现&#xff0c;小程序、h5都可以用 - DCloud 插件市场 Vue版本及cdn版本可以查阅文档&#xff1a; 行为验证 | Poster 文档 示例代码&#xff1a; <template><view id"app&…

使用阿里云的PAI-DSW进行语音关键词的训练

以前使用谷歌的Colab进行过在线的模型训练&#xff0c;不过要科学上网总是比较麻烦&#xff0c;今天第一次尝试使用阿里云的人工智能平台PAI/交互式建模&#xff08;DSW&#xff09;进行在线训练。 我采用的训练笔记本是TensorFlow的Simple audio recognition: Recognizing ke…

贝锐蒲公英视频监控方案:无需专线,实现连锁酒店摄像头集中监看

公司业务主要围绕连锁品牌酒店经营&#xff0c;从2019年成立至今&#xff0c;已经在北京、上海、杭州、武汉、南京、深圳等地设立了多家门店。为了实现集中管理&#xff0c;北京总部需要实时监看或调取各地酒店内的监控摄像头&#xff0c;并将监控数据集中存储至监控中心的服务…