常用设计模式总结

news/2024/4/19 19:02:18/文章来源:https://blog.csdn.net/weixin_51609435/article/details/128920811

复习到设计模式的时候写的一些demo代码

回头可以看看

单例的几种比较简单就没写了,专栏有

目录

观察者(发布--订阅模式)模式,多个对象依赖于一个对象,或者多对多

工厂模式:主要是封装了对象的创建(简单,方法,抽象)

简单工厂,不在23种设计模式里

工厂方法:

抽象方法:

结构型模式

代理Proxy模式demo:

适配器模式

装饰器模式,Decorator


观察者(发布--订阅模式)模式,多个对象依赖于一个对象,或者多对多

/*subject有更改 要及时通知observer去做改变
*/
class Observer{//观察者抽象类//处理消息接口public:virtual void handleEvent(int msgid)=0;
};
class Observer1:public Observer{public:void handleEvent(int msgid){ //做出相应动作switch (msgid){case 1:cout<<"Observer1 received 1"<<endl;break;case 2:cout<<"Observer1 received 2"<<endl;break;default:cout<<"Observer1 received unknown"<<endl;break;}}
};
class Observer2:public Observer{public:void handleEvent(int msgid){ //做出相应动作switch (msgid){case 2:cout<<"Observer2 received 2"<<endl;break;default:cout<<"Observer2 received unknown"<<endl;break;}}
};
//主题
class Subject{  private:unordered_map<int,list<Observer*>> _subMap;public://给主题增加观察者对象void addObserver(Observer *obser,int msgid){_subMap[msgid].push_back(obser);}//主题改变 ,通知相应的观察者去处理事件void notifyObservers(int msgid){auto it = _subMap.find(msgid);if(it != _subMap.end()){//找到了for(Observer *ob:it->second){ob->handleEvent(msgid);}}}};int main(){Subject subject;Observer *p1=new Observer1();Observer *p2=new Observer2();subject.addObserver(p1,1);subject.addObserver(p1,2);subject.addObserver(p1,3);subject.addObserver(p2,2);subject.addObserver(p2,3);int msgid;while(1){cout<<"消息id: "<<endl;cin>>msgid;subject.notifyObservers(msgid);if(msgid==-1){break;}}system("pause");return 0;
}

工厂模式:主要是封装了对象的创建(简单,方法,抽象)

简单工厂,不在23种设计模式里

简单工厂demo:把对象的创建封装在一个接口函数里,通过传入不同的标识,返回创建的对象,好处是客户不用自己负责new对象,不用了解对象具体创建的详细过程(这种设计模式不好)

缺点:提供创建对象实例的接口函数不闭合,不能对修改关闭

class Car{public:Car(string name):_name(name){}virtual void show()=0;protected:string _name;
};
class BMW:public Car
{public:BMW(string name):Car(name){}void show(){cout<<"宝马车"<<endl;}
};
class Audi:public Car
{public:Audi(string name):Car(name){}void show(){cout<<"奥迪车"<<endl;}
};enum CarType{BMw,AUDI
};
class SimpleFactory{   //封装了 对象public:Car* CreateCar(CarType type){switch(type){case BMw:return new BMW("X1");break;case AUDI:return new Audi("A6");break;default:cout<<"type err"<<endl;break;}return nullptr;}
};
int main(){SimpleFactory *fac=new SimpleFactory();Car *car=fac->CreateCar(BMw);Car *car1=fac->CreateCar(AUDI);car->show();car1->show();delete car;delete car1;delete fac;system("pause");return 0;
}

工厂方法:

把工厂划分成基类,各个子工厂去继承方法

相应的工厂只需要创建自己厂家的东西就行,还想增加奔驰,就多个奔驰工厂去继承工厂类,重写创建方法就好

对于已有的工厂不需要做改变,做到了软件工程的开闭原则

  • 工厂基类提供一个纯虚函数(创建产品),定义派生类(具体工厂),创建对应产品,可以做到不同的产品,在不同的工厂里创建,能够对现有的工厂和产品进行修改关闭
  • 实际上很多产品是有关联关系的,属于一个产品簇,不应该放在不同的工厂去创建
class Car{public:Car(string name):_name(name){}virtual void show()=0;protected:string _name;
};
class BMW:public Car
{public:BMW(string name):Car(name){}void show(){cout<<"宝马车"<<endl;}
};
class Audi:public Car
{public:Audi(string name):Car(name){}void show(){cout<<"奥迪车"<<endl;}
};//工厂方法
class Factory{
public:virtual Car* create(string name)=0;
};
//宝马工厂
class BMWFactory:public Factory{
public:Car* create(string name){return new BMW(name);}
};
//奥迪工厂
class AudiFactory:public Factory{
public:Car* create(string name){return new Audi(name);}
};
int main(){Factory *fac=new BMWFactory();Factory *fac1=new AudiFactory();Car *car=fac->create("BMw");Car *car1=fac1->create("AUDI");car->show();car1->show();delete car;delete car1;delete fac;delete fac1;system("pause");return 0;
}

抽象方法:

考虑生产一类产品,比如生产手机,耳机,充电器,总不能生产一种产品就创建一个工厂

上面的问题简单工厂无法解决,引入抽象工厂

其实就是把工厂方法叠加起来了,工厂基类的方法多了一些,子工厂继承的就多

把有关联的产品簇里的所有产品创建的接口函数,放在一个抽象工厂里,派生类(具体工厂)应该负责创建该产品簇里的所有产品

//系列产品1  汽车
class Car{public:Car(string name):_name(name){}virtual void show()=0;protected:string _name;
};
class BMW:public Car
{public:BMW(string name):Car(name){}void show(){cout<<"宝马车"<<_name<<endl;}
};
class Audi:public Car
{public:Audi(string name):Car(name){}void show(){cout<<"奥迪车"<<_name<<endl;}
};//系列产品2  车灯
class Light{public:    virtual void show()=0;
};
class BMWLight:public Light
{public: void show(){cout<<"宝马 车灯"<<endl;}
};
class AudiLight:public Light
{public:void show(){cout<<"奥迪 车灯"<<endl;}
};
//抽象工厂 对一组有关联关系的产品组提供产品的统一创建
class Factory{
public:virtual Car* createCar(string name)=0;//工厂方法virtual Light* createLight()=0;//工厂方法
};
//宝马工厂
class BMWFactory:public Factory{
public:Car* createCar(string name){return new BMW(name);}Light* createLight(){return new BMWLight();}};
//奥迪工厂
class AudiFactory:public Factory{
public:Car* createCar(string name){return new Audi(name);}Light* createLight(){return new AudiLight();}
};int main(){Factory *fac=new BMWFactory();Factory *fac1=new AudiFactory();Car *car=fac->createCar("BMw");Car *car1=fac1->createCar("AUDI");Light *l1=fac->createLight();Light *l2=fac1->createLight();car->show();l1->show();car1->show();l2->show();system("pause");return 0;
}

结构型模式

代理Proxy模式demo:

通过代理类来控制实际对象(委托类)的访问权限
客户    助理proxy   老板:委托类

class VideoSite{public:virtual void freeMovie()=0;//免费电影virtual void vipMovie()=0;//vip 电影virtual void ticketMovie()=0;//用劵
};
class FixBugVideoSite:public VideoSite{//委托类 拥有所有功能public:virtual void freeMovie(){cout<<"free movie"<<endl;}virtual void vipMovie(){cout<<"vip movie"<<endl;}virtual void ticketMovie(){cout<<"ticket movie"<<endl;}
};
//代理类 
class FreeVideoProxy:public VideoSite{
public:FreeVideoProxy(){PVideo =new FixBugVideoSite();}~FreeVideoProxy(){delete PVideo;}virtual void freeMovie(){PVideo->freeMovie();//通过代理对象的freemovie去访问真正委托类方法}virtual void vipMovie(){cout<<"you are free  cant use vip"<<endl;}virtual void ticketMovie(){cout<<"no ticket cant see movie"<<endl;}
private:VideoSite* PVideo;
};
//代理类 
class VipVideoProxy:public VideoSite{
public:VipVideoProxy(){PVideo =new FixBugVideoSite();}~VipVideoProxy(){delete PVideo;}virtual void freeMovie(){PVideo->freeMovie();//通过代理对象的freemovie去访问真正委托类方法}virtual void vipMovie(){PVideo->vipMovie();}virtual void ticketMovie(){cout<<"vip no ticket cant see movie"<<endl;}
private:VideoSite* PVideo;
};
int main()
{unique_ptr<VideoSite> p1(new FreeVideoProxy());p1->freeMovie();p1->vipMovie();p1->ticketMovie();system("pause");return 0;
}

适配器模式

让不兼容的接口可以在一起工作
电脑-》 投影到 -》 投影仪上 需要的线接口:VGA HDMI TypeC

VGA接口的电脑,投影仪也是VGA接口

HDMI的投影仪,就要用适配器去转换

class VGA{
public:virtual void play()=0;
};
//TV01表示支持VGA接口的投影仪
class TV01:public VGA{
public:void play(){cout<<"use VGA接口连接投影仪,进行视频播放"<<endl;}
};//电脑类(只支持VGA接口)
class HuaweiComputer{
public:void playVideo(VGA *vga){vga->play();}
};
/*
1.换支持hdmi接口的电脑,代码重构
2.买转换头(适配器),把vga信号转成hdmi信号,添加适配器类
*///进了一批新的投影仪,但是投影仪只支持HDMI接口
class HDMI{
public:virtual void play()=0;
};class TV02:public HDMI{
public:void play(){cout<<"use HDMI接口连接投影仪,进行视频播放"<<endl;}
};
//适配器类
class VGA_TO_HDMI:public VGA{
public:VGA_TO_HDMI(HDMI *p):pp(p){}void play(){//转换头pp->play();}
private:HDMI* pp;
};int main()
{HuaweiComputer c1;c1.playVideo(new TV01());c1.playVideo(new VGA_TO_HDMI(new TV02()));system("pause");return 0;
}

装饰器模式,Decorator

装饰器:增加现有类的功能

装饰器类持有需要被装饰的对象,装饰器再可以根据功能去细分子类

class Car{//抽象基类public:virtual void show()=0;
};
//实体类
class BMW:public Car{public:void show(){cout<<"is bmw common"<<endl;}
};
class Benz:public Car{public:void show(){cout<<"is Benz common"<<endl;}
}; 
//装饰器  定速巡航的功能
class ConcreteDecorator01:public Car{public:ConcreteDecorator01(Car *p):car(p) {}void show(){car->show();cout<<"is concrete"<<endl;}private:Car* car;
};
//装饰器  自动刹车功能
class StopDecorator01:public Car{public:StopDecorator01(Car *p):car(p) {}void show(){car->show();cout<<"is Stop"<<endl;}private:Car* car;
};int main()
{Car *p1=new ConcreteDecorator01(new Benz());p1->show();p1=new StopDecorator01(p1);p1->show();Car *p2=new StopDecorator01(new BMW());p2->show();system("pause");return 0;
}

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

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

相关文章

【word】插入mathtype公式,造成前后文本不同行

一、问题描述 在word文本中插入mathtype公式&#xff0c;在默认配置下&#xff0c;会造成前后文本不同行的现象&#xff0c;例如&#xff1a; 二、解决方案 要求1&#xff1a;字符间距位置&#xff0c;设置为“标准”&#xff1b;要求2&#xff1a;段落文本对齐方式&#x…

【原创】java+swing+txt学生学籍管理系统设计与实现

今天我们来介绍如何使用javaswingtxt来开发一个学籍管理系统。对的&#xff0c;你没看错&#xff0c;我们今天不用mysql&#xff0c;我们使用txt这个文本来进行数据存储&#xff0c;主要考察对文件读写的操作。 功能分析&#xff1a; 我们系统不要求做的很复杂&#xff0c;只…

2023从0开始学性能(2) —— 探索性能测试流程之调研需求【持续更新】

性能测试流程 性能测试的流程应该是什么样的呢&#xff1f;打开jmeter/LR &#xff0c;开启录制然后加个并发数点击运行吗&#xff1f;如果真这么简单&#xff0c;估计现在就没有性能测试这个专职的岗位了。 虽然我们没做过&#xff0c;但是有对学习的热爱和百度搜索的老手艺…

手写线程池实例并测试

前言&#xff1a;在之前的文章中介绍过线程池的核心原理&#xff0c;在一次面试中面试官让手写线程池&#xff0c;这块知识忘记的差不多了&#xff0c;因此本篇文章做一个回顾。 希望能够加深自己的印象以及帮助到其他的小伙伴儿们&#x1f609;&#x1f609;。 如果文章有什么…

【操作系统】概述

操作系统 操作系统的定义与目标 定义&#xff1a;操作系统是控制管理计算机系统的硬软件&#xff0c;分配调度资源的系统软件。 目标&#xff1a;方便性&#xff0c;有效性&#xff08;提高系统资源的利用率、提高系统的吞吐量&#xff09;&#xff0c;可扩充性&#xff0c;…

117.Android 简单的拖拽列表+防止越界拖动(BaseRecyclerViewAdapterHelper)

//1.第一步 导入依赖库和权限&#xff1a; //依赖库&#xff1a; //RecyclerView implementation com.android.support:recyclerview-v7:28.0.0//RecyclerAdapter implementation com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.28 //用到的权限&#xff1a; <!…

如何使用DevEco Studio创建Native C++应用

简介本篇主要介绍如何使用DevEco Studio for OpenAtom OpenHarmony &#xff08;以下简称“OpenHarmony”&#xff09;创建一个Native C应用。应用采用“Native C”模板&#xff0c;实现了通过Node-API调用C标准库的功能。本示例通过调用C标准库接口来演示调用过程&#xff0c;…

MES助力灯具照明行业从制造到”智造”

现如今&#xff0c;LED照明行业产品更新换代太快&#xff0c;一个产品一两年不更新一下外观、材料&#xff0c;就会被对手超越。这直接导致LED产品标准化程度不够高&#xff0c;LED下游制造类厂家智能化生产程度普遍偏低。 加之大多属于劳动密集型产业&#xff0c;传统的依靠买…

less、sass、webpack(前端工程化)

目录 一、Less 1.配置less环境 1.先要安装node&#xff1a;在cmd中&#xff1a;node -v检查是否安装node 2.安装less :cnpm install -g less 3.检查less是否安装成功&#xff1a;lessc -v 4.安装成功后&#xff0c;在工作区创建xx.less文件 5.在控制台编译less,命令&…

Ubuntu16.04使用apache创建个人用户主页并添加口令认证

文章目录一.安装apache二、apache文件和目录简述2.1 网站数据目录2.2 Apache配置文件三、创建个人用户主页3.1 开启个人用户主页功能3.2 建立目录和首页面3.3 开启模块3.4 测试四、添加口令认证4.1 生成密码数据库4.2 修改配置文件一.安装apache 创建虚拟机&#xff0c;保持默…

Python socket之TCP通信、下载文件

TCP简介TCP介绍TCP协议&#xff0c;传输控制协议&#xff08;英语&#xff1a;Transmission Control Protocol&#xff0c;缩写为 TCP&#xff09;是一种面向连接的、可靠的、基于字节流的传输层通信协议&#xff0c;由IETF的RFC 793定义。TCP通信需要经过创建连接、数据传送、…

深入浅出深度学习Pytroch

本文将以通俗易懂的方式&#xff0c;深入浅出地为您揭开深度学习模型构建与训练的面纱&#xff1a; 深度学习数据data模型model损失函数loss优化optimizer可视化visualizer深度学习 数据data 模型model 损失函数loss 优化optimizer 可视化visualizer深度学习数据data模型m…

如何写新闻稿?写好新闻稿的技巧与步骤

新闻稿是传递新闻事件和信息的重要手段&#xff0c;是传媒工作中不可或缺的一部分。写好一篇新闻稿可以让受众了解更多信息&#xff0c;进一步提高他们的关注度。以下是一些写好新闻稿的技巧和步骤&#xff0c;帮助你有效地传达新闻。1、确定新闻的核心信息在开始写新闻稿之前&…

短链或H5唤醒(跳转)APP应用

唤醒APP(两种方法) 一.短链唤醒(跳转)app ⭐ 短链跳转到APP&#xff0c;当如果用户手机不存在APP(某个应用)将会进入到官网页面。 app links实现 在android studio菜单栏Tools->App Links Ass点击,效果图如下 2.配置如下 点击ok,生成如下效果图 3.完成第二步后,会自动…

FreeRTOS入门(01):基础说明与使用演示

文章目录目的基础说明系统移植基础使用演示数据类型和命名风格总结碎碎念目的 FreeRTOS是一个现在非常流行的实时操作系统&#xff08;Real Time Operating System&#xff09;。本文将介绍FreeRTOS入门使用相关内容&#xff0c;这篇是第一篇&#xff0c;主要介绍基础背景方面…

【论文阅读】Anti-Adversarially Manipulated Attributions for WSSS

一篇CVPR2021上的论文&#xff0c;用于弱监督分割及半监督分割 论文标题&#xff1a; Anti-Adversarially Manipulated Attributions for Weakly and Semi-Supervised Semantic Segmentation&#xff08;AdvCAM&#xff09; 作者信息&#xff1a; 代码地址&#xff1a; htt…

2023年华为HCIE-Dacom认证题库(H12-891)

1、如图所示是某位网络工程师在排查OSPF故障时的输出信息。据此判断&#xff0c;以下哪种原因可能导致邻接关系无法正常建立。 Hello报文发送时间不一致认证密码不一致接口的IP地址掩码不一致区域类型不一致 正确答案&#xff1a;C 2、如图所示&#xff0c;路由器的所有接口开启…

ATTCK实战系列——红队实战(二)

网络配置 网卡&#xff1a; WEB&#xff1a; PC&#xff1a; DC&#xff1a; IPWEB10.10.10.80&#xff08;内&#xff09;/192.168.111.80&#xff08;外&#xff09;PC10.10.10.201&#xff08;内&#xff09;/192.168.111.201&#xff08;外&#xff09;DC10.10.10.10物理机…

C++线程/阻塞/同步异步----2

本章节内容为记录改写RTK代码时&#xff0c;学习的知识 同步和异步区别 1.定义不同&#xff1a;同步需要将通信双方的时钟统一到一个频率上&#xff0c;异步通信发送的字符间隔时间可以是任意的; 2.准确性不同&#xff1a;同步通信需要比较高精度的精确度&#xff0c;异步则不…

5.12 BGP选路原则综合实验

配置BGP的选路原则 1. 实验目的 熟悉BGP的选路的应用场景掌握BGP的选路的配置方法2. 实验拓扑 实验拓扑如图5-11所示: 图5-11:配置BGP的选路原则 3. 实验步骤 (1)配置IP地址 R1的配置