C++设计模式---面向对象原则

面向对象设计原则

原则的目的:高内聚,低耦合

1. 单一职责原则

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

2. 开闭原则

对扩展开放,对修改关闭;增加功能是通过增加代码来实现的,而不是去修改源代码。

#include<iostream>
using namespace std;

//开闭原则
//对扩展开放,对修改关闭;增加功能是通过增加代码来实现的,而不是去修改源代码

//写一个抽象类
class AbstractCaculator
{
public:
	virtual int getResult() = 0;
	virtual void setOperatorNumber(int a, int b) = 0;
};

//加法计算类
class AddCaculator :public AbstractCaculator
{
public:
	virtual void setOperatorNumber(int a, int b)
	{
		this->mA = a;
		this->mB = b;
	}
	virtual int getResult()
	{
		return mA + mB;
	}

public:
	int mA;
	int mB;
};

//减法计算器
class SubCaculator :public AbstractCaculator
{
public:
	virtual void setOperatorNumber(int a, int b)
	{
		this->mA = a;
		this->mB = b;
	}
	virtual int getResult()
	{
		return mA - mB;
	}

public:
	int mA;
	int mB;
};

//乘法计算器
class MolCaculator :public AbstractCaculator
{
public:
	virtual void setOperatorNumber(int a, int b)
	{
		this->mA = a;
		this->mB = b;
	}
	virtual int getResult()
	{
		return mA * mB;
	}

public:
	int mA;
	int mB;
};

//取模计算器	通过增加代码来实现
class MulCaculator :public AbstractCaculator
{
public:
	virtual void setOperatorNumber(int a, int b)
	{
		this->mA = a;
		this->mB = b;
	}
	virtual int getResult()
	{
		return mA % mB;
	}

public:
	int mA;
	int mB;
};

void test01()
{
	AbstractCaculator* caculator = new AddCaculator;
	caculator->setOperatorNumber(10, 20);
	cout << "ret:" << caculator->getResult() << endl;
	delete caculator;

	caculator = new SubCaculator;
	caculator->setOperatorNumber(10, 20);
	cout << "ret:" << caculator->getResult() << endl;
}

int main()
{
	test01();
	return 0;
}

3. 里氏代换原则

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

4. 依赖倒转原则

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

传统方式:

#include<iostream>
using namespace std;

//银行工作人员
class BankWorker
{
	public:
		void saveService()
		{
			cout << "办理存款业务..." << endl;
		}
		void payService()
		{
			cout << "办理支付业务..." << endl;
		}
		void tranferService()
		{
			cout << "办理转账业务..." << endl;
		}
};

//中层模块
void doSaveBussiness(BankWorker* worker) {
	worker->saveService();
}

void doPayBussiness(BankWorker* worker) {
	worker->payService();
}

void doTranferBussiness(BankWorker* worker) {
	worker->tranferService();
}


void test04() {
	BankWorker* worker = new BankWorker;
	doSaveBussiness(worker);  //办理存款业务
	doPayBussiness(worker); //办理支付业务
	doTranferBussiness(worker); //办理转账业务
}

int main()
{
	test04();
    return 0;
}

依赖倒转原则: 

#include<iostream>
using namespace std;

//银行工作人员
class AbstractWorker
{
public:
	virtual void doBusiness() = 0;
};

//专门办理存款业务的工作人员
class SaveBankWorker :public AbstractWorker
{
public:
	virtual void doBusiness()
	{
		cout << "办理存款业务..." << endl;
	}
};

//专门办理支付业务的工作人员
class PayBankWorker :public AbstractWorker
{
public:
	virtual void doBusiness()
	{
		cout << "办理支付业务..." << endl;
	}
};

//专门办理转账业务的工作人员
class TransferBankWorker :public AbstractWorker
{
public:
	virtual void doBusiness()
	{
		cout << "办理转账业务..." << endl;
	}
};

//中层业务
void doNewBussiness(AbstractWorker* worker)
{
	worker->doBusiness();
}

void test04_1()
{
	AbstractWorker* transfer = new TransferBankWorker;
	doNewBussiness(transfer);
}

int main()
{
	test04_1();
	return 0;
}

5. 接口隔离原则

        不应该强迫用户的程序依赖他们不需要的接口方法。一个接口应该只提供一种对外功能,不应该把所有操作都封装到一个接口中去。 

6. 迪米特法则(最少知识原则) 

        一个对象应当对其他对象尽可能少的了解,从而降低各个对象之间的耦合,提高系统的可维护性。例如在一个程序中,各个模块之间相互调用时,通常会提供一个统一的接口来实现。这样其他模块不需要了解另外一个模块的内部实现细节,这样当一个模块内部的实现发生改变时,不会影响其他模块的使用。(黑盒原理)

#include<iostream>
#include<string>
#include<vector>
using namespace std;

//迪米特法则---最少知识原则
class AbstractBuilding
{
public:
	virtual void sale() = 0;
	virtual string getQuality() = 0;
};

//楼盘A
class BuildingA : public AbstractBuilding
{
public:
	BuildingA()
	{
		m_Quality = "高品质";
	}
	virtual void sale()
	{
		cout << "楼盘A" << m_Quality << "被售卖!" << endl;
	}
	virtual string getQuality()
	{
		return m_Quality;
	}

public:
	string m_Quality;
};

//楼盘B
class BuildingB : public AbstractBuilding
{
public:
	BuildingB()
	{
		m_Quality = "低品质";
	}
	virtual void sale()
	{
		cout << "楼盘B" << m_Quality << "被售卖!" << endl;
	}

	virtual string getQuality()
	{
		return m_Quality;
	}
public:
	string m_Quality;
};

//客户端
void test02()
{
	BuildingA* ba = new BuildingA;
	if (ba->m_Quality == "高品质")
	{
		ba->sale();
	}

	BuildingB* bb = new BuildingB;
	if (bb->m_Quality == "低品质")
	{
		bb->sale();
	}
}

//中介类
class Mediator
{
public:
	Mediator()
	{
		AbstractBuilding* building = new BuildingA;
		vBuilding.push_back(building);

		building = new BuildingB;
		vBuilding.push_back(building);
	}

	//对外提供接口
	AbstractBuilding* findMyBuilding(string quality)
	{
		for (vector<AbstractBuilding*>::iterator it = vBuilding.begin(); it != vBuilding.end(); it++)
			if ((*it)->getQuality() == quality)
			{
				return *it;
			}
		return NULL;
	}

	~Mediator()
	{
		for (vector<AbstractBuilding *>::iterator it = vBuilding.begin();it != vBuilding.end();it++)
			if (*it != NULL)
			{
				delete* it;
			}
	}

public:
	vector<AbstractBuilding *> vBuilding;
};

void test02_1()
{
	Mediator* meidator = new Mediator;
	AbstractBuilding* building = meidator->findMyBuilding("高品质");
	if (building != NULL)
	{
		building->sale();
	}
	else
	{
		cout << "没有符合条件的楼盘!" << endl;
	}
}

int main()
{
	test02();
	test02_1();
	return 0;
}

7. 合成复用原则

如果使用继承,会导致父类的任何变换都可能影响到子类的行为。

如果使用对象组合,就降低了这种依赖关系。
对于继承和组合,优先使用组合。

#include<iostream>
using namespace std;

//抽象车
class AbstructCar
{
public:
	virtual void run() = 0;
};

//大众车
class Dazhong :public AbstructCar
{
public:
	virtual void run()
	{
		cout << "大众车启动" << endl;
	}
};

//拖拉机
class Tuolaji :public AbstructCar
{
public:
	virtual void run()
	{
		cout << "拖拉机启动" << endl;
	}
};

//针对具体类,不适用继承
#if 0
class Person :public Tuolaji
{
public:
	void Douofeng()
	{
		run();
	}
};

class PersonB :public Dazhong
{
public:
	void Douofeng()
	{
		run();
	}
};
#endif

//可以使用组合
class Person
{
public:
	void setCar(AbstructCar *car)
	{
		this->car = car;
	}
	void Doufeng()
	{
		this->car->run();
		if (this->car != NULL)
		{
			delete this->car;
			this->car = NULL;
		}
	}

public:
	AbstructCar* car;
};

void test03()
{
	Person* p = new Person;
	p->setCar(new Dazhong);
	p->Doufeng();
	
	p->setCar(new Tuolaji);
	p->Doufeng();

	delete p;
}

//继承和组合 优先使用组合
int main()
{
	test03();
	return 0;
}

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

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

相关文章

webpack5零基础入门-15样式兼容性问题处理

1.下载相关依赖 npm i postcss-loader postcss postcss-preset-env -D 2.在webpack.config.js中配置 注意&#xff1a;postcss-loader要在css-loader后面配置 3.写一个flex布局&#xff0c;flex是存在一定的兼容性问题的 4.打包 可以看到打包后未被处理 1.下载相关依赖 np…

js实现鼠标拖拽多选功能

实现功能 在PC端的H5页面中&#xff0c;客户拖动鼠标可以连选多个选项 效果展示 具体代码如下 <!DOCTYPE html> <html><head><title>鼠标拖拽多选功能</title><script src"https://cdn.bootcss.com/jquery/1.10.2/jquery.min.js&quo…

【Text2SQL 经典模型】TypeSQL

论文&#xff1a;TypeSQL: Knowledge-Based Type-Aware Neural Text-to-SQL Generation ⭐⭐⭐ Code: TypeSQL | GitHub 一、论文速读 本论文是在 SQLNet 网络上做的改进&#xff0c;其思路也是先预先构建一个 SQL sketch&#xff0c;然后再填充 slots 从而生成 SQL。 论文发…

Epson推出多摄像头接口芯片S2D13P04

目前&#xff0c;汽车电子的发展日新月异&#xff0c;汽车显示控制器也更多地采用芯片集成化设计的趋势伴随着目前ADAS系统的发展&#xff0c;大量的摄像头和雷达传感器应用到汽车电子中。传统的系统集成方案通常采用多通道电路来处理多摄像头信号输入的方案&#xff0c;但是车…

Oracle体系结构初探:数据库启动与停止

往期内容 参数管理 控制文件添加 启动 在启动Oracle数据库时&#xff0c;我们一般会使用如下命令&#xff1a; startup 虽然命令只有一个&#xff0c;但其中却是经历了3个阶段&#xff0c;从下面执行 startup 命令返回也可以看出来。 总结为3个阶段&#xff1a; nomount&…

正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-22讲 RTC 时钟设置

前言&#xff1a; 本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM&#xff08;MX6U&#xff09;裸机篇”视频的学习笔记&#xff0c;在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。…

GPT‑4o普通账户也可以免费用

网址 https://chatgpt.com/ 试了一下&#xff0c;免费的确实显示GPT‑4o的模型&#xff0c;问了一下可以联网&#xff0c;不知道能不能通过插件出图 有兴趣的可以试试

测试环境KDE组件漏洞修复

yarn白名单方案 解决漏洞: 方案: 此方式主要使用iptables的功能,对yarn的resourceManager服务的8088端口进行访问ip限制,目的限制8088端口只允许集群内ip访问。 #分别在两台resourceManager节点执行以下步骤ssh kde-offline1 #安装iptables服务,并启动设置为开机自启 yum …

【Android】WorkManager(章二)

剩余的三部分 官方文档 案例 实现下载器&#xff0c;并监听下载进度 界面 定义Worker 在官方案例的前提下&#xff0c;进行完善 下载download 下载进度 授予权限 开始工作并监听 完整代码 MainActivity.java package com.test.downloadworkerapplication;import static…

键盘盲打是练出来的

键盘盲打是练出来的&#xff0c;那该如何练习呢&#xff1f;很简单&#xff0c;看着屏幕提示跟着练。屏幕上哪里有提示呢&#xff1f;请看我的截屏&#xff1a; 截屏下方有8个带字母的方块按钮&#xff0c;这个就是提示&#xff0c;也就是我们常说的8个基准键位&#xff0c;我…

Redis学习篇2:Redis在IEDA中的应用

本文继上文开始讲述了Redis在IDEA中如何应用以及集成进入spring开发环境&#xff0c;以及如何使用Redis客户端。上一个文章&#xff1a;Redis学习篇1&#xff1a;初识Redishttps://blog.csdn.net/jialuosi/article/details/139057088 一、Redis在java中的客户端 二、SpringDat…

通联支付API集成(适用于SpringBoot)

目标&#xff1a; 学习如何使用Java与通联支付API进行交互 实现一个简单的支付下单和查询订单状态的示例 所需材料&#xff1a; 通联支付API文档 官方文档https://aipboss.allinpay.com/know/devhelp/main.php?pid38#mid313 通联支付加签代码SybUtil package com.allin…

从GPT-4o和Google I/O看AI技术变革与未来趋势

引言 在科技界的激烈竞争中&#xff0c;OpenAI 和 Google 这两大巨头不断推出新技术&#xff0c;引领着人工智能的发展。最近&#xff0c;OpenAI 发布了 GPT-4o&#xff0c;恰逢 Google I/O 大会前一天&#xff0c;这一发布会似乎有意“截胡” Google I/O。今天&#xff0c;我…

python实现520表白图案

今天是520哦&#xff0c;作为程序员有必要通过自己的专业知识来向你的爱人表达下你的爱意。那么python中怎么实现绘制520表白图案呢&#xff1f;这里给出方法&#xff1a; 1、使用图形库&#xff08;如turtle&#xff09; 使用turtle模块&#xff0c;你可以绘制各种形状和图案…

go 爬虫之 colly 简单示例

1. 背景 colly 是 Go 实现的比较有名的一款爬虫框架&#xff0c;而且 Go 在高并发和分布式场景的优势也正是爬虫技术所需要的。它的主要特点是轻量、快速&#xff0c;设计非常优雅&#xff0c;并且分布式的支持也非常简单&#xff0c;易于扩展。 2. 官方文档 https://go-col…

大模型的实践应用24-LLaMA-Factory微调通义千问qwen1.5-1.8B模型的实例

大家好,我是微学AI,今天给大家介绍一下大模型的实践应用24-LLaMA-Factory微调通义千问qwen1.5-1.8B模型的实例, LLaMA-Factory是一个专门用于大语言模型微调的框架,它支持多种微调方法,如LoRA、QLoRA等,并提供了丰富的数据集和预训练模型,便于用户进行模型微调。通义千问…

15:00面试,15:08就出来了,问的问题有点变态。。。

从小厂出来&#xff0c;没想到在另一家公司又寄了。 到这家公司开始上班&#xff0c;加班是每天必不可少的&#xff0c;看在钱给的比较多的份上&#xff0c;就不太计较了。没想到8月一纸通知&#xff0c;所有人不准加班&#xff0c;加班费不仅没有了&#xff0c;薪资还要降40%…

mysql 慢查询

一、开启mysql自己的慢查询日志 1、查看慢日志参数设置 show VARIABLES like %query% 2、修改配置文件 vim /etc/my.cnf [mysqld] slow_query_log 1 #是否开启慢查询日志记录 long_query_time 1 #慢查询时间&#xff0c;单位秒 #log_outputtable,file #慢查询…

学习Thymeleaf时遇到的问题

使用idea创建web项目&#xff0c;启动服务器后无法访问页面 原因是tomcat 新版本引用包名改变 由javax变为jakarta 解决办法1 把项目的poe.xml文件由 改为 解决办法2 新建项目时选择新版本&#xff0c;但是新版本不支持thymeleaf

基础2 JAVA图形编程桌面:探索图形程序的抽象实现

嘿&#xff0c;大家好&#xff01;我非常高兴又一次有机会与大家相聚&#xff0c;分享新的知识和经验。对于热爱编程和探索新技术的朋友们来说&#xff0c;今天的内容绝对不容错过。我为大家准备了一个详尽的视频教程&#xff1a;《基础2 JAVA 图形编程&#xff1a;主程序调用…