C++ 设计模式

news2024/12/26 2:56:14

设计模式

  • 创建型模式
    • 工厂方法模式
    • 抽象工厂模式
    • 单例模式
    • 建造者模式(生成器模式)
    • 原型模式
  • 结构型模式
    • 适配器模式
    • 装饰器
    • 代理模式
    • 外观模式
    • 桥接模式
    • 组合模式(部分--整体模式)
    • 享元模式
  • 行为型模式
    • 策略模式
    • 模板模式
    • 观察者模式
    • 迭代器模式
    • 责任链模式
    • 命令模式
    • 状态模式
    • 备忘录模式(快照模式)
    • 访问者模式
    • 中介者模式
    • 解释器模式

设计模式,依据设计目的分为三种:创建型模式、结构型模式、行为型模式
创建型模式包括:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式
结构型模式包括:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式包括:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

创建型模式

工厂方法模式

由自己根据需要直接实例化对象
	OBJ *obj;
	if []
		obj = new obj1();
	else
		obj = new obj2();

抽象工厂模式

由工厂分发对象

	OBJ obj = Factory("xxx");

单例模式

全局仅一个该类型对象,可以在尝试使用时候实例化,也可以程序初始化(编译、程序启动时候)时候实例化

	OBJ::GetInstance();

建造者模式(生成器模式)

某些对象的初始化需要多个步骤完成,可以将它交给一个director来初始化,以此达到统一的代码实现

	O o;
	o.setBuilder(builder)
	o.builder();

原型模式

单纯一个深拷贝

	OBJ obj1
	OBJ obj2(obj1)

结构型模式

适配器模式

没什么好说的,就是将同种功能,但实现方式不同的接口、类按照一致的形态进行编写,达到可以任意切换接口、类的目的

装饰器

实现方式有些类似于回调函数,以完成对所需要增加的属性值一一调用接口增加的目的
在这里插入图片描述

	class Parent
	{
		virtual void Fun(void)=0;
	}
	class Product : public Parent{
		void Fun(void) override
		{
			//TODO: pass
		}
	}
	class decorator1: public Parent{
		decorator1(Parent & parent):_parent(parent){};
		void Fun(void) override
		{
			_parent.Fun();
		}
		Parent &_parent;
	}
	class decorator2: public Parent{
		decorator2(Parent & parent):_parent(parent){};
		void Fun(void) override
		{
			_parent.Fun();
		}
		Parent &_parent;
	}

相关代码

代理模式

使用代理服务,隐藏原本的类,可用于团队开发,各自负责各自的部分,也可以使用一个小一点的class暴漏或者分等级暴露接口,减少系统维护难度
下述代码可以使用委托类的Request接口

template<class T>
class Proxy
{
    public:
        Proxy(){};
        Proxy(T* sub){m_sub=sub;}; //代理主题角色中定义了一个真实主题角色对象
        ~Proxy(){delete m_sub;};
        void Request()  //代理主题角色也实现了抽象主题角色的方法
        {
            cout<<"Proxy REQ"<<endl;
            m_sub->Request();//代理主题角色调用 真实角色的业务方法
        }
    private:
        T* m_sub;
};

外观模式

个人觉得比较扯淡的一个模式,好比我们喝水,非要说说喝的是H2O, 明明就是一个接口封装,逐级封装, 貌似刚学代码时候就需要了解的东西,下面是从其他博主那边找的例子
点击调准实例地址

#include <iostream>
using namespace std;
//外观模式就是将复杂的子类系统抽象到同一个接口进行管理,
//外界只需要通过此接口与子类系统进行交互,
//而不必要和复杂的子类系统进行交互
class Television //电视机类
{
public:
	void On(){
		cout << "电视机打开" << endl;
	}
	void Off() {
		cout << "电视机关闭" << endl;
	}
};
class Gamemachine //游戏机类
{
public:
	void On() {
		cout << "游戏机打开" << endl;
	}
	void Off() {
		cout << "游戏机关闭" << endl;
	}
};
class Microphone //麦克风类
{
public:
	void On() {
		cout << "麦克风打开" << endl;
	}
	void Off() {
		cout << "麦克风关闭" << endl;
	}
};
class Sound //音响类
{
public:
	void On() {
		cout << "音响打开" << endl;
	}
	void Off() {
		cout << "音响关闭" << endl;
	}
};
class Light //灯类
{
public:
	void On() {
		cout << "灯打开" << endl;
	}
	void Off() {
		cout << "灯关闭" << endl;
	}
};
class DVD //DVD类
{
public:
	void On() {
		cout << "DVD打开" << endl;
	}
	void Off() {
		cout << "DVD关闭" << endl;
	}
};
class Facade
{
public:
	Facade() {
		ds = new   Television;
		yxj = new    Gamemachine;
		mkf = new   Microphone;
		yx = new   Sound;
		d     = new Light;
		dvd  = new DVD;
	}
	void KTVPattern()//KTV模式
	{
		cout << "KTV模式启动中,请稍后!" << endl;
		ds->On();
		d->Off();
		mkf->On();
		yx->On();
		dvd->On();
	}
	void GamePattern() //游戏机模式
	{
		cout << "游戏机模式启动中,请稍后!" << endl;
		ds->On();
		yx->On();
		yxj->On();
	}
	~Facade() {
		delete ds;
		delete yxj;
		delete mkf;
		delete yx;
		delete d;
		delete dvd;
	}
private:
	Television*ds;
	Gamemachine*yxj;
	Microphone*mkf;
	Sound*yx;
	Light*d;
	DVD*dvd;
};
void test() {
	Facade*myFacade = new Facade;
	myFacade->KTVPattern();
	myFacade->GamePattern();
}
void main() {
	test();
}


桥接模式

顾名思义,牵线搭桥。 该模式适用于双发没有从属关系、没有上下级关系的场景。
建立一个桥接类,将两个互不统属的类进行关联调用。
实际场景可以参考各个手机的应用商店功能。
相关代码

组合模式(部分–整体模式)

适用于上下级且能够抽象出一致性的场景中,
比如传销组织的结构,开个玩笑,不过传销组织的确很时候使用组合模式。

class PyramidSale {
	string m_string;
	virtual void add(PyramidSale  *)=0;
}
class Level1 :public PyramidSale 
{
	vector<PyramidSale *> m_vecComp;
	void add(PyramidSale  *) override;
}
class Level12:public PyramidSale 
{
	vector<PyramidSale *> m_vecComp;
	void add(PyramidSale  *) override;
}

int main(void)
{
	PyramidSale *l1 = new Level1();
	PyramidSale *l2_1 = new Level2();
	PyramidSale *l2_2 = new Level2();

	l1->add(l2_1);
	l1->add(l2_2);
}

享元模式

共享资源的一种模式,
由于系统开发环节中,很多资源属于能够被公用的,比如某个图片资源、某个音频资源
如果每个对象使用它的时候加载一次,耗费时间,而且多个对象同时加载同一个资源,又浪费内存资源
争对此,提出享元模式

即:某一大型资源加载时候,先查询享元类(可以理解为一个共享空间),在这个空间内使用hash map对资源进行缓存, 如果不存在, 再从flash中加载资源,否则直接从享元类中获取,节省时间与空间

享元类中可以做一个循环队列,某些长时间不使用的大型资源,可以释放掉。
代码链接

行为型模式

策略模式

与工厂模式一样,所不同的是目的不同,也就是应用场景不同,
工厂模式侧重于实例化对象,
策略模式侧重于类中接口的实现,也就是算法的实现

模板模式

class Leader {
	public:
		void run(void)
		{
			a();
			b();
			c();
		}
		virtual void a()==0;
		virtual void b()==0;
		virtual void c()==0;
}

class OfficClerk : Leader{
	public:
		void a() override
		{

		}
		void b() override
		{

		}
		void c() override
		{

		}
}
int main()
{
	Leader *leader = new OfficClerk ();
	leader->run();
}

观察者模式

其他作者是这么描述的:
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新

核心解决方案:回调函数

class Observer {
	public:
		virtual void update()= 0;
}
templete <class T>
class Subject {
	private:
		std::list<T *> _objectServerList;
	public:
		void attach(T *object) {
			_objectServerList.push_back(t);
		}
		void detach(T *object) {
			_objectServerList.remove(t);
		}
		void Notify() {
			for(auto object=_objectServerList.begin();object!=_objectServerList.end();object++)
			{
				(*object)->update();
			}
		}
}

迭代器模式

一种遍历的手段,比如链表就是一种迭代器的表现方式,

责任链模式

还是定义不同的接口、或者对象,来将任务拆分成不同的任务(责任)进行
每个接口、对象完成一部分,达到简化代码的目的

命令模式

核心思想:命令模式的作用是将请求封装为一个对象,将请求的发起者和执行者解耦,支持对请求排队以及撤销和重做。
下例中,将Receiver中的两个请求封装成为了两个对象,然后通过命令来进行执行
声明:代码抄袭自链接, 然后使用模板类实现,增强适应性

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>

using namespace std;

// 接受者,作为最底层的调用
class Receiver
{
public:
        void BakeMutton()
        {
                cout<< "烤羊肉"<< endl;
        }

        void BakeChicken()
        {
                cout<< "烤鸡翅"<< endl;
        }
};

// 基类
template <class T>
class Command
{
public:
        Command(T* pstReceiver):m_pstReceiver(pstReceiver)
        {
            cout << "m_pstReceiver" << endl;
        };
        ~Command();
        virtual void Excute() = 0;

// protected:
        T* m_pstReceiver;
};

// 具体类,用于调用接收者
template <class T>
class ConcreteCommandA: public Command<T>
{
public:
        ConcreteCommandA(T* pstReceiver) : Command<T>(pstReceiver)
        {
            
        }
        virtual void Excute()
        {
                cout<< "ConcreteCommandA excuting......"<< endl;
                this->m_pstReceiver->BakeMutton();
        }

};

// 具体类,用于调用接收者
template <class T>
class ConcreteCommandB: public Command<T>
{
public:
        ConcreteCommandB(T* pstReceiver):Command<T>(pstReceiver)
        {

        }
        virtual void Excute()
        {
                cout<< "ConcreteCommandB excuting......"<< endl;
                this->m_pstReceiver->BakeChicken();
        }
};

// 调用者,作为最上层,用于管理具体类的操作,从而对接收者增删
template <class T>
class Invoke
{
public:
        void Add(Command<T>* pstCommand)
        {
                m_vecPstCommand.push_back(pstCommand);
        }
        void Remove(Command<T>* pstCommand)
        {
                m_vecPstCommand.erase(find(m_vecPstCommand.begin(), m_vecPstCommand.end(), pstCommand));
        }
        void RemoveAll()
        {
                m_vecPstCommand.clear();
        }
        void Notify()
        {
                for (typeof(m_vecPstCommand.begin()) it = m_vecPstCommand.begin(); it != m_vecPstCommand.end(); ++it)
                {
                        (*it)->Excute();
                }
        }

private:
        vector<Command<Receiver>*> m_vecPstCommand;
};

int main(int argc, char* argv[])
{
        Receiver* pstReceiver = new Receiver();
        Command<Receiver>* pstConcreteCommandA = new ConcreteCommandA<Receiver>(pstReceiver);
        Command<Receiver>* pstConcreteCommandB = new ConcreteCommandB<Receiver>(pstReceiver);
        Invoke<Receiver>* pstInvoke = new Invoke<Receiver>();

        pstInvoke->Add(pstConcreteCommandA);
        pstInvoke->Add(pstConcreteCommandA);
        pstInvoke->Add(pstConcreteCommandB);
        pstInvoke->Notify();
        cout<< "------------------"<< endl<< endl;

        pstInvoke->Remove(pstConcreteCommandA);  //撤销操作
        pstInvoke->Remove(pstConcreteCommandB);
        pstInvoke->Notify();
        cout<< "------------------"<< endl<< endl;

        return 0;
}

状态模式

主要目的是处理状态机之类的事务, 将每个状态封装成为一个单独的类,再借由一个上下文类将所有状态管理起来,每个状态可以借由上下文类切换到其他状态
在这里插入图片描述

备忘录模式(快照模式)

在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将该对象恢复到原先保存的状态
个人觉得这个没有什么好聊的,无非就是建立一个管理者类,自己制定好规则,在什么时候将需要备份的类复制进管理者中,在需要的时候拷贝出来就可以完成恢复

访问者模式

有些复杂,还没看懂

中介者模式

该模式提出的设想在于:使用一个中介者来管理所有客户,使得他们能够互相通信,由客户1 改变 客户2 或者客户3 的状态
解除了代码上存在的耦合性
依然抄袭代码,改为模板方式以增加适配性

#include <iostream>
#include <list>

using namespace std;

class Colleague;

//定义一个中介者接口,包含对象改变所需调用函数。
template <class T>
class Mediator
{
public :
    virtual ~Mediator()
    {

    }
    virtual void changed(T *)=0;

protected:
    std::list<T *> _colleague;

};

//定义"同事"类接口,初始化需要一个中介者对象,并通过该类更新另外一个"同事"
class Colleague
{
public :
    //初始化中介者类对象
    Colleague(Mediator<Colleague> * mediator)
    {
        this->mediator =mediator;
    }
    //更新另外一个类
    virtual void changed()
    {
        mediator->changed(this);
    }
    virtual void update()=0;
private:
    Mediator<Colleague> *mediator;
};

//具体的同事类1
class ConcreteColleague1 :public Colleague
{
public:
    ConcreteColleague1(Mediator<Colleague> * mediator):Colleague(mediator)
    {
    }
    void update()
    {
        cout<<"update ConcreteColleague1 from ConcreteColleague2"<<endl;
    }
};
//具体的同事类2
class ConcreteColleague2 :public Colleague
{
public :
    ConcreteColleague2(Mediator<Colleague> * mediator):Colleague(mediator)
    {
    }
    void update()
    {
        cout<<"update ConcreteColleague2 from ConcreteColleague"<<endl;
    }
};

//具体的中介者类,实现更新函数changed。
class ConcreteMediator :public Mediator<Colleague>
{
public:
    void setColleague(Colleague * colleague)
    {
        this->_colleague.push_back(colleague);
    }
    ConcreteMediator()
    {
        //colleague1 = new ConcreteColleague(this);

    }
    ~ConcreteMediator()
    {

    }
    virtual void changed(Colleague* colleague)
    {
        for(auto begin=this->_colleague.begin(); begin!=this->_colleague.end(); begin++)
        {
            if(*begin != colleague)
            {
                (*begin)->update();
            }
        }
    }

};
main()
{
    ConcreteMediator concreteMediator;
    ConcreteColleague1  colleague1(&concreteMediator);
    ConcreteColleague2  colleague2(&concreteMediator);
    concreteMediator.setColleague(&colleague1);
    concreteMediator.setColleague(&colleague2);
    //"同事1"通过中介者更新"同事2"
    colleague1.changed();
    //"同事2"通过中介者更新"同事1"
    colleague2.changed();

}

解释器模式

这个代码是真不会写,csdn上看到的一些解释器的代码,我不觉得有太高的学习价值。
它主要是一个文本分析器,将语法规则设置进去之后,可以分析一段文本的含义。

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

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

相关文章

对抗js前端加密的万能方法

1、前言 现在越来越多的网站采用全报文加密&#xff0c;测试的时候需要逆向提取加密算法以及密钥&#xff0c;过程十分繁琐和复杂。本文提供一种更为简单快捷的方法来解决此问题。 原理大致如下&#xff1a;使用浏览器的Override Hook加密前的数据&#xff0c;配置代理地址发…

[Linux]Linux编译器-gcc/g++

&#x1f941;作者&#xff1a; 华丞臧. &#x1f4d5;​​​​专栏&#xff1a;【LINUX】 各位读者老爷如果觉得博主写的不错&#xff0c;请诸位多多支持(点赞收藏关注)。如果有错误的地方&#xff0c;欢迎在评论区指出。 推荐一款刷题网站 &#x1f449; LeetCode刷题网站 文…

SpringBoot+Redis(官方案例)

在线文档项目结构 1.源码克隆&#xff1a;git clone https://github.com/spring-guides/gs-messaging-redis.git 2.包含两个项目initial和complete&#xff0c;initial可以根据文档练习完善&#xff0c;complete是完整项目 3.功能描述&#xff1a;构建应用程序&#xff0c;使用…

【谷粒商城基础篇】商品服务:商品维护

谷粒商城笔记合集 分布式基础篇分布式高级篇高可用集群篇简介&环境搭建项目简介与分布式概念&#xff08;第一、二章&#xff09;基础环境搭建&#xff08;第三章&#xff09;整合SpringCloud整合SpringCloud、SpringCloud alibaba&#xff08;第四、五章&#xff09;前端知…

xxx.lua入门编程

lua入门级编程,openresty的前置技能lua入门级编程,openresty的前置技能 看上图 lua示例&#xff1a; 入门示例 print("hello world!") local arr {"java","mysql","oracle"}; local map {usernamezhangsan,password123}; local fu…

Debezium 同步 PostgreSQL 数据到 RocketMQ 中

1.RocketMQ Connect概览 RocketMQ Connect是RocketMQ数据集成重要组件&#xff0c;可将各种系统中的数据通过高效&#xff0c;可靠&#xff0c;流的方式&#xff0c;流入流出到RocketMQ&#xff0c;它是独立于RocketMQ的一个单独的分布式&#xff0c;可扩展&#xff0c;可容错系…

字节二面:Redis 的大 Key 对持久化有什么影响?

Redis 的持久化方式有两种&#xff1a;AOF 日志和 RDB 快照。 所以接下来&#xff0c;针对这两种持久化方式具体分析分析。 大 Key 对 AOF 日志的影响 先说说 AOF 日志三种写回磁盘的策略 Redis 提供了 3 种 AOF 日志写回硬盘的策略&#xff0c;分别是&#xff1a; Always&am…

Git(四) - Git 分支操作

​​​​​​​ 一、什么是分支 在版本控制过程中&#xff0c;同时推进多个任务&#xff0c;为每个任务&#xff0c;我们就可以创建每个任务的单独分支。使用分支意味着程序员可以把自己的工作从开发主线上分离开来&#xff0c;开发自己分支的时候&#xff0c;不会影响主线分支…

前端面试常考 | js原型与原型链

文章目录一. 什么是原型?二. 什么是原型链?一. 什么是原型? 在js中所有的引用类型都有一个__proto__(隐式原型)属性&#xff0c;属性值是一个普通的对象。 而在js中的引用类型包括&#xff1a;Object&#xff0c;Array&#xff0c;Date&#xff0c;Function 而所有函数都有…

基于K8s的DevOps平台实践(二)

文章目录1. 流水线入门&#x1f351; 流水线基础语法&#x1f351; 脚本示例&#x1f351; 脚本解释&#x1f351; Blue Ocean2. Jenkinsfile实践&#x1f351; 演示一&#x1f351; 演示二&#x1f351; 演示三&#x1f351; 演示四&#x1f351; 总结3. 多分支流水线实践&…

BEV视觉3D感知算法梳理

1. 基于BEV空间的自动驾驶感知任务 最近&#xff0c;基于BEV空间下的感知任务已经涌现出了众多优秀算法&#xff0c;并在多个自动驾驶公开数据集&#xff08;KITTI&#xff0c;Waymo&#xff0c;nuScenes&#xff09;上取得了非常不错的成绩。根据自动驾驶汽车上安装的传感器类…

【从零开始学习深度学习】37. 深度循环神经网络与双向循环神经网络简介

目录1. 深度循环神经网络2. 双向循环神经网络总结1. 深度循环神经网络 之前介绍的循环神经网络只有一个单向的隐藏层&#xff0c;在深度学习应用里&#xff0c;我们通常会用到含有多个隐藏层的循环神经网络&#xff0c;也称作深度循环神经网络。下图演示了一个有LLL个隐藏层的…

数字化时代,全方位解读商业智能BI

商业智能BI是一种通用的数据类技术解决方案&#xff0c;不会因为行业BI没有进行针对性开发而出现不适配、无法使用的情况。同时&#xff0c;也正因为商业智能BI核心是数据&#xff0c;只要企业有数据沉淀&#xff0c;不管是哪些行业BI商业智能都能发挥出作用。 不过考虑到不同…

文件IO操作开发笔记(一):使用Qt的QFile对磁盘文件存储进行性能测试以及测试工具

文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/128438303 红胖子(红模仿)的博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结…

portraiture2023智能磨皮修饰滤镜插件中文版

在人像后期修图的时候免不了需要进行磨皮处理&#xff0c;很多人在挑选磨皮软件的时候都不知道该如何选择&#xff0c;今天的文章就来带大家看看磨皮软件哪个好&#xff0c;能磨皮的修图软件和插件!借助磨皮软件即使是新手也能做出高级的人像图片&#xff0c;下面挑选了几款好用…

Java 并发编程知识总结【五】

6. 线程中断与 LockSupport 6.1 线程中断机制 大厂&#xff08;蚂蚁金服&#xff09;面试题&#xff1a; 什么是中断&#xff1f; 首先&#xff0c;一个线程不应该由其他线程来强制中断或停止&#xff0c;而是应该由线程自己自行停止。所以&#xff0c;Thread.stop, Thread.…

Exynos_4412——中断控制器

目录 一、中断控制器 中断控制器的作用&#xff1a; 二、Exynos_4412下的中断控制器 它支持三种类型的中断 可以编程设置&#xff1a; 三、中断控制器详解 四、中断控制器编程 一、中断控制器 外设产生的中断信号&#xff0c;先要经过中断控制器&#xff0c;中断是异常…

如何解决软件项目管理中的冲突?

1、项目干系人间的良好沟通 项目干系人之间保持良好的沟通交流&#xff0c;是减少项目管理中冲突的重要手段。甲乙双方签订合同后&#xff0c;为保障项目的成功&#xff0c;在项目发生矛盾和困难时&#xff0c;需要双方相互理解和沟通&#xff0c;共同协商解决问题。 为了及时解…

Git(八) - IDEA 集成 GitHub

一、设置 GitHub 账号 二、分享工程到 GitHub 来到GitHub中发现已经帮我们创建好了git-test的远程仓库。 三、push 推送本地库到远程库 注意&#xff1a;push是将本地库代码推送到远程库&#xff0c;如果本地库代码跟远程库代码版本不一致&#xff0c; push的操作是会被拒绝的…

go 性能分析pprof和trace

runtime/pprof&#xff1a;采集程序&#xff08;非 Server&#xff09;的运行数据进行分析&#xff0c;用于可结束的代码块&#xff0c;如一次编解码操作等net/http/pprof&#xff1a;采集 HTTP Server 的运行时数据进行分析。用于不可结束的代码块&#xff0c;如 web 应用等 使…