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

news2024/11/17 14:22:22

面向对象设计原则

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

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;
}

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

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

相关文章

10G SFP双口万兆以太网控制器,高速光口网络接口卡

2-Port 10G SFP NIC 是一款高速网 络接口卡&#xff0c;采用了 PCI Express 3.0 x8 接口&#xff0c;支持双 端口万兆以太网&#xff0c;具有高性能、高可靠性、低功耗等 优点&#xff0c;是数据中心、云计算、虚拟化等领域的理想选 择。 支持多种网络协议&#xff0c;如 …

不懂平面设计,这篇文章教你制作商业画册

​商业画册不仅是企业展示形象、推广产品的重要工具&#xff0c;也是设计师展现创意的平台。因此&#xff0c;制作一本高质量的画册对于企业来说至关重要。 那要怎么着手制作呢&#xff1f;以下是关于制作商业画册的步骤。 1.要制作电子杂志,首先需要选择一款适合自己的软件。…

从失败开始浅谈如何交易现货白银

投资者进入现货白银市场&#xff0c;可以说目的就是在这个市场中盈利&#xff0c;只有极少数朋友是想在这个市场中冒险&#xff0c;体验一下资金盈亏所带来的刺激。然而&#xff0c;投资者在交易现货白银的时候&#xff0c;由于一心想获利&#xff0c;因此他们很怕谈失败&#…

Python学习---基于进程池的文件夹copy器案例

# 思路&#xff1a; # 1、定义变量&#xff0c;保存源文件和目标文件夹的路径 # 2、在目标路径创建新的文件夹 # 3、获取源文件夹中的所有文件&#xff08;列表&#xff09; # 4、遍历列表得到所有文件名 # 5、定义函数进行文件拷贝 # 文件拷贝函数&#xff1a; # 参数&#xf…

基于manifest文件批量将coding的仓库导入gitlab中

文章目录 写在前面的话背景编写manifest文件最终效果 写在前面的话 前面有讲过通过manifest清单导入项目到gitlab中&#xff0c;但是实际的操作是不同gitlab实例之间的操作&#xff0c;然而对于在不同gitlab实例的repo迁移而言&#xff0c;显然direct transfer会更合适。 背景…

房地产画册制作成手机在线翻页效果

​随着科技的飞速发展&#xff0c;移动互联网已经深入到人们的日常生活中。在这个数字化的时代&#xff0c;房地产行业也紧跟潮流&#xff0c;将画册制作成手机在线翻页效果&#xff0c;以满足消费者的阅读习惯。 房地产画册制作成手机在线翻页效果&#xff0c;不仅能够满足消费…

Win10【无线显示器】安装失败(无法添加)解决中。。。

目录 ■失败现象 ■解决方法 【服务启动1】 【服务确认】 【服务启动2】 参考 ■查看电脑是否支持【Miracast无线投屏功能】 参考2 ■解决方法&#xff08;对我的这台电脑有效&#xff09; ■解决后的效果 ■连接时&#xff0c;出现【无法在此设备上查看受保护内容。…

时空扭曲:重温相对论的终极挑战,探寻真理的脚步

大家都知道&#xff0c;相对论是爱因斯坦提出的划时代理论&#xff0c;为人类认知时空和引力做出了革命性贡献。但这个理论真的万无一失吗&#xff1f;近日&#xff0c;一项新研究提出了测试时间扭曲的新方法&#xff0c;或许能让我们重新审视相对论在宇宙大尺度上的适用性。 时…

安卓高级控件(下拉框、列表类视图、翻页类视图、碎片Fragment)

下拉框 此小节介绍下拉框的用法以及适配器的基本概念&#xff0c;结合对下拉框Spinner的使用说明分别阐述数组适配器ArrayAdapter、简单适配器SimpleAdapter的具体用法与展示效果。 下拉框控件Spinner Spinner是下拉框控件&#xff0c;它用于从一串列表中选择某项&#xff0…

时代终结,微软宣布淘汰VBScript;Flink漏洞被广泛利用;Grandoreiro银行木马强势回归,1500多家银行成攻击目标 | 安全周报0524

揭秘SolarMarker恶意软件&#xff1a;多层次基础设施让清除工作陷入困境 Recorded Future的新发现表明&#xff0c;SolarMarker信息窃取恶意软件背后的持续威胁行为者已经建立了一个多层次的基础设施&#xff0c;以使执法部门的清除工作变得复杂。 该公司在上周发布的一份报告…

三菱机械手维修控制器故障

在工业自动化领域&#xff0c;三菱工业机器人凭借其高性能、高可靠性和易用性&#xff0c;受到了广泛应用。然而&#xff0c;随着时间的推移&#xff0c;可能会出现MITSUBISH工业机械臂控制器故障&#xff0c;需要进行三菱机械手维修。 一、MITSUBISH机械手控制器故障诊断 在进…

如何基于springboot构建cas最新版源码?

环境准备 下载JDK21 https://download.oracle.com/java/21/archive/jdk-21.0.2_windows-x64_bin.zip下载gradle 8.5并配置环境变量 https://gradle.org/next-steps/?version8.5&formatbin下载项目git clone http://gitlab.ruishan.cc/meta/anka-authentication.git 开始…

C++---运算符重载

运算符重载介绍 在类中重新定义运算符&#xff0c;赋予运算符新的功能以适应类的运算&#xff0c;就称为运算符重载。 运算符重载是一种形式的C多态,它使得对象操作更直观,本质上也是属于函数重载。 实际上&#xff0c;我们已经在不知不觉之中使用了运算符重载。例如&#xff…

ElasticSearch操作之重置密码脚本

ElasticSearch操作之重置密码脚本 #!/bin/bash # 使用样例 ./ES密码重置.sh 旧密码 新密码# 输入旧密码 es_old_password$1# 设置新的密码变量 es_password$2# 正确响应 es_reponse{"acknowledged":true}# 检查Elasticsearch是否在运行 if pgrep -f elasticsearch &g…

用WPS将多张图片生成一个pdf文档,注意参数设置

目录 1 新建一个docx格式的文档 2 向文档中插入图片 3 设置页边距 4 设置图片大小 5 导出为pdf格式 需要把十几张图片合并为一个pdf文件&#xff0c;本以为很简单&#xff0c;迅速从网上找到两个号称免费的在线工具&#xff0c;结果浪费了好几分钟时间&#xff0c;发现需要…

电影《朝云暮雨》观后感

上周看了电影《朝云暮雨》&#xff0c;看完之后&#xff0c;感觉自己整个人都不太好了&#xff0c;也不是说电影太差&#xff0c;只是觉得电影没有传达正能量&#xff0c;让人很不舒服。 &#xff08;1&#xff09;演技在线 对于著名的演员“范伟”&#xff0c;或者说&#x…

邮件系统数据面临的安全问题及解决方法

随着电子邮件的普及&#xff0c;邮件系统已成为企业、学校、个人等用户之间进行信息交流的重要工具。然而&#xff0c;随着数据量的增加和用户对邮件系统的依赖&#xff0c;邮件系统数据安全问题也逐渐凸显。下面U-Mail技术张工就给大家讲解一下邮件系统数据面临的主要安全问题…

权限维持--windows

隐藏文件 ①文件属性隐藏 如何排查&#xff1a; 使用dir命令无法看到有特殊属性的文件需使用/a ②真隐藏 相当于给原本的文件增加系统文件属性、存档文件属性、只读文集属性、隐藏文件属性 如何排查&#xff1a; 取消受保护的操作系统文件 ③利用ADS隐藏 使用数据流 echo &…

远动通讯屏的原理和应用

远动通讯屏的原理和应用 远动通讯屏&#xff0c;是一种集显示和远程控制于一体的智能化控制设备。它可以通过网络、通信线路等方式实现与远程设备的通讯和交互&#xff0c;从而实现远程监控和控制。 远动通讯屏实现远程控制的核心原理是基于PLC&#xff08;Programmable Logic …

SpringCloud Alibaba Nacos分类配置--多方案配置隔离

文章目录 Nacos 分类配置(实现配置隔离)1.DataID 方案需求分析/图解配置实现测试 2.Group 方案需求分析/图解配置实现修改application.yml修改bootstrap.yml测试 3.Namespace 方案需求分析/图解配置实现修改application.yml修改bootstrap.yml测试 Namespace/Group/Data ID 关系…