5 面试--设计模式

五、设计模式

        

设计模式是在软件开发中,经过验证的、在特定场景的解决⽅案。另⼀种说法是扩展隔离变化点,抽象稳定点。

5.1 设计原则

1. 单⼀职责原则:就⼀个类⽽⾔,应该仅有⼀个引起它变化的原因。
2. 开放封闭原则:对程序的改动可以通过增加代码来完成,但是不能改动现有的代码
3. ⾥⽒代换原则:如果⼀个实体适⽤⼀个基类,那么⼀定适⽤于其派⽣类
4. 依赖倒置原则:针对接⼝编程,不要针对实现编程
5. 迪⽶特原则:如果⼀个类需要调⽤另⼀个类的某个⽅法的话,可以通过第三个类转发这个调⽤
6. 接⼝隔离原则:每个接⼝中不应该存在派⽣类⽤不到却必须实现的⽅法,否则就要将接⼝拆分

5.2 常⽤设计模式

单例模式

保证⼀个类仅有⼀个实例,并提供⼀个访问它的⽅法。有饿汉模式和懒汉模式两种,饿汉模式是该类定义的时候进⾏实例化,且是线程安全的。
饿汉式
class Singleton
{public:static Singleton *getInstance(){return instance;}private:// Singleton() = default;Singleton() {}Singleton(const Singleton &instance) = default;Singleton &operator=(const Singleton &instance) = default;static Singleton *instance;
};Singleton *Singleton::instance = new Singleton();

懒汉式

#include <mutex>class Singleton
{public:static Singleton *getInstance(){if (instance == nullptr){mtx.lock();if (instance == nullptr){instance = new Singleton();}mtx.unlock();}return instance;}private:Singleton() = default;Singleton(const Singleton &instance) = default;Singleton &operator=(const Singleton &instance) = default;static Singleton *instance;static mutex mtx;
};mutex Singleton::mtx;
Singleton *Singleton ::instance = nullptr;

简单⼯⼚模式

主要⽤于创建对象。⽤⼀个⼯⼚来根据输⼊的条件产⽣不同的类,然后依据不同类的虚函数得到不同的结果。创建对象之间⽆依赖。产品基类定义纯虚函数,其派⽣类实现该虚函数。⼯⼚类定义返回产品接⼝的函数,通过判断传⼊的参数确定返回产品类型。

#include <bits/stdc++.h>
using namespace std;
class IProduct {
public:
virtual void show() = 0;virtual ~Product(){};
};
class ProductA : public IProduct {
public:
void show() {
cout << "ProductA.show()" << endl;
}
~ProductA(){};
};
class ProductB : public IProduct {
public:
void show() {
cout << "ProductB.show()" << endl;
}
~ProductB(){};
};
class SimpleFactory {
public:
IProduct* product(const string str) {
if (str == "productA") {
return new ProductA();
}
else if (str == "productB") {
return new ProductB();
}
return nullptr;
}
};
int main() {
SimpleFactory fac;
IProduct* pro;
pro = fac.product("productA");
pro->show();
delete pro;
pro = fac.product("productB");
pro->show();
delete pro;
return 0;
}

模板⽅法

定义⼀个操作中的算法框架,⽽将⼀些步骤延迟到⼦类中。该⽅法使得⼦类可以不改变⼀个算法的结构即可重定义该算法的某些特定步骤。基类实现总处理步骤顺序的函数,⽽每个步骤定义为虚函数。派⽣类实现所要改变某步骤的虚函数即可。
        
#include <bits/stdc++.h>
using namespace std;
class Show {
public:
void show() { // 固定流程封装到这⾥
show0();
show1();
show2();
show3();
}
protected:
// ⼦流程 允许⼦类访问,防⽌客户调⽤
virtual void show0() {
cout << "show0" << endl;
}
virtual void show1() {
cout << "show1" << endl;
}
virtual void show2() {
cout << "show2" << endl;
}
virtual void show3() {
cout << "show3" << endl;
}
};
class ShowEx: public Show {
protected:
virtual void show1() {
cout << "show1 update" << endl;
}
virtual void show2() {
cout << "show2 update" << endl;
}
};
int main() {
Show* zs = new ShowEx;
zs->show();return 0;
}

责任链模式

使多个对象都有机会处理请求,从⽽避免请求的发送者和接收者之间存在耦合关系。将这些对象连成⼀条链,并沿着这条链传递请求,直到有个对象处理它为⽌。基类有个指向⾃⼰的指针next,还有两个函数,分别是定义为纯虚函数的处理函数和设置下⼀个对象的函数。派⽣类实现虚处理函数(包含⾃⼰的处理逻辑、传递给下⼀个对象操作、⽆法处理对应的操作等)
#include <bits/stdc++.h>
using namespace std;
class IHandler {
protected:
IHandler *next;
public:
void setNextHandler(IHandler* n) { next = n; }
virtual bool handleRequest(string ctx) = 0;
};
class HandleByMainProgram: public IHandler {
public:
virtual bool handleRequest(string ctx) {
if (ctx == "1") {
cout << "HandleByMainProgram" << endl;
}
else if (next){
next->handleRequest(ctx);
}
else {
cout << "NO" << endl;
}
}
};
class HandleByProjMgr: public IHandler {
public:
virtual bool handleRequest(string ctx) {
if (ctx == "2") {
cout << "HandleByProjMgr" << endl;
}
else if (next){
next->handleRequest(ctx);
}
else {
cout << "NO" << endl;
}
}
};
class HandleByBoss: public IHandler {
public:
virtual bool handleRequest(string ctx) {
if (ctx == "3") {
cout << "HandleByBoss" << endl;
}
else if (next){
next->handleRequest(ctx);
}
else {
cout << "NO" << endl;
}
}
};
int main() {
IHandler *h1 = new HandleByMainProgram();
IHandler *h2 = new HandleByProjMgr();
IHandler *h3 = new HandleByBoss();
h1->setNextHandler(h2);
h2->setNextHandler(h3);
h1->handleRequest("3");return 0;
}

装饰器模式

动态地给对象增加额外的功能。就增加功能⽽⾔,该模式⽐⽣成⼦类更为灵活。(与责任链最⼤不同在于是否有顺序关系)。 基类有⼀个指向⾃⼰的指针变量,同时有⼀个原始功能函数,被定义为虚函数。派⽣类实现该虚函数,并通过基类指针调⽤基类的功能函数。
#include <bits/stdc++.h>
using namespace std;
class CalcBonus {
public:
CalcBonus(CalcBonus *c = nullptr): cc(c) {}
virtual double calc(Context &ctx) {
return 0.0;
}
protected:
CalcBonus *cc;
};
class CalcMonthBonus: public CalcBonus {
public:
CalcMonthBonus(CalcBonus *c): CalcBonus(c) {}
virtual double Calc(Context &ctx) {
double mbonus = 0.0;
return mbonus + cc->calc(ctx);
}
};
class CalcSumBonus: public CalcBonus {
public:
CalcSumBonus(CalcBonus *c): CalcBonus(c) {}
virtual double Calc(Context &ctx) {
double sbonus = 0.0;
return sbonus + cc->calc(ctx);
}
};
class CalcGroupBonus: public CalcBonus {
public:
CalcGroupBonus(CalcBonus *c): CalcBonus(c) {}
virtual double Calc(Context &ctx) {
double gbonus = 0.0;
return gbonus + cc->calc(ctx);
}
};
int main() {
// 普通员⼯
Context ctx1;
CalcBonus *base = new CalcBonus();
CalcBonus *cb1 = new CalcMonthBonus(base);
CalcBonus *cb2 = new CalcSumBonus(cb1);
cb2->calc(ctx1);
// 部⻔经理
Context ctx2;
CalcBonus *cb3 = new CalcGroupBonus(cb2);
cb3->calc(ctx2);return 0;
}

观察者设计模式,如何实现

1. 观察者设计模式的定义
多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到
通知并被自动更新 。这种模式有时又称作发布 - 订阅模式、模型 - 视图模式,它是对象行为型模式。
2. 优点
1 降低了目标与观察者之间的耦合关系 ,两者之间是抽象耦合关系。符合依赖倒置原则。
2 目标与观察者之间建立了一套触发机制。
3. 缺点
1 )目标与观察者之间的依赖关系并没有完全解除,而且有可能出 现循环引用。
2 当观察者对象很多时,通知的发布会花费很多时间,影响程序的效率。
4. 观察者设计模式的结构与实现
观察者模式的主要角色如下:
1 抽象主题 Subject )角色:也叫抽象目标类,它提供了一个用于保存观察者对象的聚集类和
增加、删除观察者对象的方法,以及通知所有观察者的抽象方法。
2 具体主题 Concrete Subject )角色:也叫具体目标类,它实现抽象目标中的通知方法,当
具体主题的内部状态发生改变时,通知所有注册过的观察者对象。
3 抽象观察者 Observer )角色:它是一个抽象类或接口,它包含了一个更新自己的抽象方
法,当接到具体主题的更改通知时被调用。
4 具体观察者 Concrete Observer )角色:实现抽象观察者中定义的抽象方法,以便在得到
目标的更改通知时更新自身的状态。
可以举个博客订阅的例子,当博主发表新文章的时候,即博主状态发生了改变,那些订阅的读者就会收 到通知,然后进行相应的动作,比如去看文章,或者收藏起来。博主与读者之间存在种一对多的依赖关系。
#include <iostream>
#include <vector>
#include <list>
#include <memory>
#include <algorithm>
using namespace std;//观察者 --用户
class Observer
{
public:Observer() {}virtual ~Observer() {}virtual void Update() {}
};//博客  --主题
class Blog
{
public:Blog() {}virtual ~Blog() {}void Attach(Observer *observer){m_observers.push_back(observer);}void Remove(Observer *observer){m_observers.remove(observer);}void Notify(){list<Observer *>::iterator iter = m_observers.begin();for (; iter != m_observers.end(); iter++){(*iter)->Update();}}virtual void SetStatus(string s){m_status = s;} //设置状态virtual string GetStatus(){return m_status;} //获得状态private:list<Observer *> m_observers; //观察者链表protected:string m_status; //状态。
};//具体 主题
class BlogCSDN : public Blog
{
private:string m_name;public:BlogCSDN(string name) : m_name(name) {}~BlogCSDN() {}virtual void setStatus(string s){m_status = "CSDN 通知:" + m_name + s; //具体设置状态信息}string GetStatus(){return m_status;}
};//具体观察者。
class ObserverBlog : public Observer
{private:string m_name;Blog *m_blog;public:ObserverBlog(string name, Blog *blog) : m_name(name), m_blog(blog) {}~ObserverBlog() {}void Update(){string status = m_blog->GetStatus();cout << m_name << "--------------------" << status << endl;}
};//测试案例。
int main()
{Blog *blog = new BlogCSDN("wuzhekai1985");Observer *observer1 = new ObserverBlog("tutupig", blog);blog->Attach(observer1);blog->SetStatus("Publishing Design Pattern C++Implementation (15) - Observer Pattern");blog->Notify();delete blog;delete observer1;system("pause");return 0;
}

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

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

相关文章

Linux 栈回溯

目录 前言一、什么是栈回溯&#xff1f;二、栈回溯的实现原理三、参考阅读 前言 日常工作中&#xff0c;我们在开发软件程序时&#xff0c;经常会遇到程序奔溃的问题&#xff0c;导致程序奔溃的原因有很多&#xff0c;我们一般都是定位到相关代码&#xff0c;再去查询具体原因。…

C# 使用PanGu分词

写在前面 这是官方介绍&#xff1a;盘古分词是一个中英文分词组件。作者eaglet 曾经开发过KTDictSeg 中文分词组件&#xff0c;拥有大量用户。作者基于之前分词组件的开发经验&#xff0c;结合最新的开发技术重新编写了盘古分词组件。 盘古分词组件需要配合其字典文件使用&am…

虚幻学习笔记—文本内容处理

一、前言 本文使用的虚幻引擎5.3.2&#xff0c;在虚幻中已经集成了很多可以直接处理多样化文本的蓝图&#xff0c;比如格式化动态显示、浮点数多样化等。 二、实现 2.1、格式化文本显示动态内容&#xff1a;在设置某个文本时可以使用“Format Text”蓝图设置自定义可以的显示…

1.6锁的升级过程

一、偏向锁 轻量级锁 当有新的线程进来时 其实就是竞争不激烈&#xff0c;但是确实存在多个锁竞争的情况&#xff0c;而且是&#xff0c;大家都很有序的进行&#xff0c;一释放&#xff0c;下一个线程就拿到锁&#xff0c;很有顺序的获取锁&#xff0c;基本上通过自旋的方式代…

一、Oceanbase基础

一、集群相关概念 集群&#xff1a;整个分布式数据库。Region&#xff1a;表示区域&#xff0c;是地域的逻辑概念&#xff0c;如1个城市&#xff0c;1个集群可以有多个Region&#xff0c;用于跨城市远 距离容灾。Zone&#xff1a;表示分区&#xff0c;是机房或机架的逻辑概念…

Git指定分支或文件回退到指定版本

文章目录 一、分支回滚1.1、使用 git reset 命令1.2、使用 git revert 命令1.3、使用 git checkout 命令 二、文件回滚2.1、回滚未提交文件2.2、回滚已提交文件2.2.1、首先查看文件的历史版本2.2.2、找到你想要还原的版本2.2.3、将文件还原到你想要还原的版本2.2.4、提交代码 三…

Scrapy爬虫异步框架之持久化存储(一篇文章齐全)

1、Scrapy框架初识&#xff08;点击前往查阅&#xff09; 2、Scrapy框架持久化存储 3、Scrapy框架内置管道&#xff08;点击前往查阅&#xff09; 4、Scrapy框架中间件&#xff08;点击前往查阅&#xff09; Scrapy 是一个开源的、基于Python的爬虫框架&#xff0c;它提供了…

Android应用程序开发实战篇----期末总结1

项目1&#xff08;了解移动电子商务开发&#xff09; 1,任务一&#xff1a;了解移动电子商务 移动电子商务&#xff1a;利用无线终端进行的电子商务活动。 移动电子商务的特点&#xff1a;方便&#xff0c;摆脱时空性&#xff0c;安全&#xff0c;潜在用户规模大&#xff0c;…

vue day2

1、指令修饰符&#xff1a;.指明一些指令后缀&#xff0c;不同后缀封装不同处理操作 按键修饰符&#xff1a;keyup.enter v-model修饰符&#xff1a; v-model.trim&#xff1a;去首位空格 v-model.number&#xff1a;转数字 事件修饰符&#xff1a; 阻止事件冒泡&#xff1…

目标检测YOLO系列从入门到精通技术详解100篇-【目标检测】工业相机

目录 知识储备 深度相机 1 TOF 2 双目视觉 3 结构光 4 智能门锁应用 5 手机应用

sftp学习

什么是sftp&#xff1f; sftp的简单操作 远程连接 int RobostSftp::Init(QString ip,QString port,QString user_name, QString user_password) { int rc;session ssh_new();if (!session) {fprintf(stderr, "ssh initialization failed\n");// return 1…

新版idea如何开启多台JVM虚拟机

1.看看自己的项目 2.可能开始的时候啥也没有&#xff0c;就点Run Configuration Type 3.再点击Edit Configurations... 4.点击号添加SpringBoot 5.主类选择一下&#xff0c;一般就一个&#xff0c;点他选了就行。 6.然后点击Modify Options 选择添加add VM Options 7.点击appl…

云服务器哪家便宜?亚马逊AWS等免费云服务器推荐

在这数字化的时代&#xff0c;云计算技术越来越广泛应用于各种场景&#xff0c;尤其是云服务器&#xff0c;作为一种全新的服务器架构正在逐渐取代传统的物理服务器&#xff0c;“云服务器哪家便宜”等用户相关问题也受到越来越多的关注。自从亚马逊最早推出了首个云计算服务—…

如何解决主从数据库同步延迟问题?

如何解决主从数据库同步延迟问题&#xff1f; 前言 最近&#xff0c;系统上频繁出现主从延迟的问题&#xff0c;因此针对主从架构、主从同步以及主从延迟问题进行了一次学习。 主从架构浅析 在了解主从延迟之前&#xff0c;我们有必要对主从架构有一些简单的认识。在如今的…

2023-11-26 LeetCode每日一题(统计子串中的唯一字符)

2023-11-26每日一题 一、题目编号 828. 统计子串中的唯一字符二、题目链接 点击跳转到题目位置 三、题目描述 我们定义了一个函数 countUniqueChars(s) 来统计字符串 s 中的唯一字符&#xff0c;并返回唯一字符的个数。 例如&#xff1a;s “LEETCODE” &#xff0c;则其…

深度学习及其基本原理

深度学习的 Ups and Downs概念区分神经网络的构成深度学习基本原理深度学习的普遍近似定理扩展&#xff1a;反卷积网络——可视化每一层提取的特征 深度学习的 Ups and Downs 1958&#xff1a;感知机&#xff08;线性模型&#xff09;1969&#xff1a;感知机有局限性1980s&…

SpringCloud-高级篇(五)

一&#xff1a;分布式事务理论基础 原子性&#xff08;Atomicity&#xff09; 原子性是指事务是一个不可分割的工作单位&#xff0c;事务中的操作要么都发生&#xff0c;要么都不发生。 一致性&#xff08;Consistency&#xff09; 事务前后数据的完整性必须保持一致。 隔离性&…

【九章斩题录】Leetcode:面试题 01.03. URL化(C/C++)

精品题解 &#x1f525; 《九章斩题录》 &#x1f448; 猛戳订阅 面试题 01.03. URL化 &#x1f4da; 题目&#xff1a;URL化。编写一种方法&#xff0c;将字符串中的空格全部替换为%20。假定该字符串尾部有足够的空间存放新增字符&#xff0c;并且知道字符串的“真实”长度。…

【JDK21】详解虚拟线程

目录 1.概述 2.虚拟线程是为了解决哪些问题 2.1.线程切换的巨大代价 2.2.哪些情况会造成线程的切换 2.3.线程资源是有限的 3.虚拟线程 4.适用场景 1.概述 你发任你发&#xff0c;我用JAVA8&#xff1f;JDK21可能要对这句话say no了。 现在Oracle JDK是每4个版本&#x…

最新版小权云黑系统 骗子添加查询源码

小权云黑系统添加骗子&#xff0c;查询骗子&#xff0c;可添加团队后台方便审核用&#xff0c;在线反馈留言系统&#xff0c;前台提交骗子&#xff0c;后台需要审核才能过&#xff0c;后台使用光年UI界面&#xff0c;新增导航列表&#xff0c;可给网站添加导航友链&#xff0c;…