C++ 面向对象五大原则

判断两个多边形是否相交(java实现) 判断两个多边形是否相交 ,当前认为一个点相交也是相交,可针对凹多边形和凸边型等多复杂的多边形进行相交判断,采用java实现,因为网上java实现的比较少,所以这里写下如何实现,适用于碰撞检测,地图等等应用场景 阅读详情

一,面向对象五大原则

1,理解设计模式与设计原则

软件设计原则: 原则为我们提供指南,它告诉我们什么是对的,什么是错的。它不会告诉我们如何解决问题。它仅仅给出一些准则,以便我们可以设计好的软件,避免不良的设计。
软件设计模式: 模式是在软件开发过程中总结得出的一些可重用的解决方案,它能解决一些实际的问题。一些常见的模式,比如工厂模式、单例模式等等。 封装、继承、多态只是类的三大特性,在程序设计时并不是说使用到了这三个特性就是面向对象,真正的面向对象的设计要满足下面五个原则。

2,单一功能原则

原理: 单一职责原则可以看作是低耦合、高内聚在面向对象原则上的引申,将功能定义为引起变化的原因,功能过多可能引起它变化的原因就越多,这将导致功能依赖,相互之间就产生影响,从而极大的损伤其内聚性和耦合度。因此不要为类实现过多的功能,以保证一个类只有一个引起它变化的原因。

class DBManager{
private:
    string userId;
public:
    DBManager(const string &str):userId(str){}
    void add(){
        if(userId == "chongchong"){
            //执行往数据库里添加数据的操作
        }
    }
};

程序分析:

上面这个是很low的设计,如果验证用户权限的规则或数据库的操作发生改变,那就必须对DBManager类进行修改。权限判断的功能和数据库操作的功能被放在一个类中。我们可以使用Proxy模式,实现权限判断与数据库操作功能的分离。DBManager类实现数据库操作,代理Proxy类里面进行权限判断,下面这个是比较高大上的设计:

class Protocal{
public:
    virtual void add();
};

class DBManager : public Protocal{
private:
    string userId;
public:
    DBManager(const string &str):userId(str){}
    void add(){
        //添加一条记录到数据库中
    }
};

class Proxy : public Protocal{
private:
    DBManager &manager;
public:
    Proxy(const DBManager &db):manager(db){}
    void add(){
        //先对用户的权限进行验证,然后再执行往数据库添加数据的操作
        manager.add();
    }
};

int main() {
    DBManager manager("123456");
    Proxy delegate(manager);
    delegate.add();
    return 0;
}

3,开放封闭原则

**原理:**对扩展是开放的,对修改是封闭的。开放封闭原则主要体现在下面两个方面,一是:对扩展开放意味着,软件有新的需求或变化时,可以对现有的代码进行扩展,以满足新的需求。二是:对修改封闭意味着,类一旦设计完成,就不要对类进行任何的修改。“需求总是变化”、“世界上没有一个软件是不变的”,这些言论是对软件需求最经典的表白。对于软件设计者来说,必须在不需要对原有的系统进行修改的情况下,实现灵活的系统扩展。而如何能做到这一点呢? 要面向接口编程,而不是面向实现编程。实现开放封闭的核心思想就是对抽象编程,而不对具体编程,因为抽象相对稳定。让类依赖于固定的抽象,所以对修改就是封闭的;而通过面向对象的继承和对多态机制,通过接口可以派生出新的类,实现新功能的扩展,所以对于扩展就是开放的,这是实施开放封闭原则的基本思路。
**实例:**设计一款射击游戏,在这个游戏中会出现不同的人物角色以及不同的枪支,人物与枪支是最容易扩展的部分,把他们隔离开来,形成统一的接口处理。具体的人物角色与枪支都是依赖于这些接口,此时对接口的修改就是封闭的,而通过继承从抽象类派生出新的类,就是对扩展的开放,下面就是类的设计:

class Gun{
public:
    virtual void kill();
};

class MachineGun : public Gun{
public:
    void kill(){
        cout<<"MachineGun."<<endl;
    }
};

class Character{
public:
    virtual void shoot(){}
};

class BadGuy : public Character{
private:
    Gun &weapon;
public:
    BadGuy(Gun &gun):weapon(gun){}
    void shoot(){
        cout<<"BadGuy use ";
        weapon.kill();
    }
};

int main() {
    MachineGun machineGun;
    BadGuy badGuy(machineGun);
    badGuy.shoot();
    return 0;
}

输出结果:

BadGuy use MachineGun.

Process returned 0 (0x0)   execution time : 0.006 s
Press any key to continue.

程序分析:

所有的具体类都是依赖于接口,具体类之间没有耦合在一起。例如:所有的Character的派生类,都是与接口Gun耦合在一起,都使用的是接口中提供的方法。

4,替换原则

**原理:**子类应当可以替换父类,并能出现在父类能出现的任何位置上,主要就是继承的体现。继承是一项非常优秀的语言机制,它可以提高代码复用性与代码的可扩展性。这个原则的核心思想就是,良好的继承定义了一个规范。
实例: CS是一款经典的射击游戏,下面是枪类的实现。
这里写图片描述

5,依赖倒转原则

原理: 抽象不能依赖于具体,具体应该依赖于抽象。就是要面向接口编程,而不是面向实现编程。
**实例:**假设我们现在要做一个电商系统,会遇到这样一个问题:订单入库。假设系统设计初期,用的是SQL Server数据库。通常我们会定义一个SqlServer类,用于数据库的读写。

class SqlServer{
public:
    void add(){
        cout<<"往数据库添加一个订单."<<endl;
    }
};

然后定义一个Order类,负责订单的逻辑处理。由于订单要入库,需要依赖于数据库的操作。因此在Order类中,需要定义SqlServer类的变量并初始化。

class Order{
private:
    SqlServer *p;
public:
    Order(){
        p = new SqlServer;
    }
    void add(){
        //先进行订单的逻辑处理,再把这个订单放到数据库
        p->add();
    }
};

定义上面两个类很容易实现想要的功能,但是可能有一天不想使用SQL Server数据库,要使用Oracle数据库,那么要重新写一个OracleServer类,然后对Order类进行修改。如果底层数据库换成Mysql,又要进行类似的操作,所以设计的系统的扩展性不强。主要的原因有两个,一是:Order直接依赖于一个具体的类,二是:Order依赖的对象的创建与绑定是在它的内部实现的。高层模块Order类不应该依赖于低层模块SqlServer,两者应该依赖于抽象。可以使用IoC(控制反转)来解决上面的问题。IoC有2种常见的实现方式:依赖注入和服务定位。其中,依赖注入是使用最为广泛,下面将深入理解依赖注入(DI)。

什么是依赖注入(DI)?

控制反转(IoC)一种重要的方式,就是将依赖对象的创建和绑定转移到被依赖对象类的外部来实现。在上述的实例中,Order类所依赖的对象SqlServer的创建和绑定是在Order类内部进行的。事实证明,这种方法并不可取。既然,不能在Order类内部直接绑定依赖关系,那么如何将SqlServer对象的引用传递给Order类使用呢?依赖注入(DI),它提供一种机制,将需要依赖(低层模块)对象的引用传递给被依赖(高层模块)对象。通过DI,可以在Order类的外部将SqlServer对象的引用传递给Order类对象。

使用构造函数来实现依赖注入

构造函数注入,毫无疑问通过构造函数传递依赖。因此,构造函数的参数必然用来接收一个依赖对象。那么参数的类型是什么呢?具体依赖对象的类型?还是一个抽象类型?根据DIP原则,知道高层模块不应该依赖于低层模块,两者应该依赖于抽象。那么构造函数的参数应该是一个抽象类型。首选,需要定义SqlServer的抽象类型DataAccess。

class DataAccess{
public:
    virtual void add(){}
} ;

class SqlServer : public DataAccess{
public:
    void add(){
        cout<<"往 SQL 数据库添加一个订单."<<endl;
    }
};

class Oracle : public DataAccess{
public:
   void add(){
     cout<<"往 Oracle 数据库添加一个订单."<<endl;
   }
};

修改Order类:

class Order{
private:
    DataAccess &re;
public:
    Order(DataAccess &re):re(re){}
    void add(){
        //先进行订单的逻辑处理,再把这个订单放到数据库
        re.add();
    }
};

下面是main函数:

int main() {
    SqlServer sql;         //在外部创建依赖对象
    Order order1(sql);     //通过构造函数注入依赖
    order1.add();

    Oracle oracle;         //在外部创建依赖对象
    Order order2(oracle);  //通过构造函数注入依赖
    order2.add();
    return 0;
}

输出结果:

往 SQL 数据库添加一个订单.
往 Oracle 数据库添加一个订单.

Process returned 0 (0x0)   execution time : 0.009 s
Press any key to continue.

程序分析:

显然,不需要修改Order类的代码,就完成了Oracle数据库的移植,这无疑体现了IoC的精妙。

6,接口分离原则

原理: 使用多个专门的接口,而不使用单一的总接口,即类不应该依赖那些它不需要的接口。

class Worker{
public:
    virtual void eat();
    virtual void work();
};

现在有两个类实现了这个接口,一是Manager,另一个是ChengXuYuan,下面是这两个类的实现

class Manager : public Worker{
public:
    void eat(){
        cout<<"Manager eat."<<endl;
    }
    void work(){
        cout<<"Manager work."<<endl;
    }
};

class ChengXuYuan : public Worker{
public:
    void eat(){
        cout<<"ChengXuYuan eat."<<endl;
    }
    void work(){
        cout<<"ChengXuYuan work."<<endl;
    }
};

现在引入一个Robot,来实现上面的Worker接口,work行为对机器人来说是可以接受的,但是eat行为对机器人来说,就非常的不合理。如果直接让Robot实现Worker接口,此时的Robot就被迫使用它用不到的接口,当接口Worker发生变化时,它同样也要跟着改变。使用适配器模式解决上面的问题,下面是代码:

class EatAdapter : public Worker{
    void eat();
};

class WorkAdapter : public Worker{
    void work();
};

使用适配器模式,把一个大的接口,分成几个小的接口。

Qwen2.5-7B大模型实战:从零部署到高效推理全流程解析 本文详细解析了Qwen2.5-7B大模型从零部署到高效推理的全流程。内容涵盖环境准备、模型下载、使用Transformers进行核心对话推理,并深入介绍了vLLM与TGI生产级服务部署、GPTQ/AWQ量化技术以降低显存消耗,以及llama.cpp、Ollama等本地推理方案。旨在帮助开发者快速掌握部署技巧,实现大模型在消费级硬件上的高效运行。 阅读详情

相关推荐

Gromacs实战:从蛋白质-小分子对接到分子动力学模拟全流程解析

本文详细解析了使用Gromacs进行蛋白质-小分子复合物分子动力学模拟的全流程。从处理AutoDock等对接软件的结果文件开始,逐步指导如何为蛋白质和小分子分别生成拓扑文件,并解决力场合并的核心挑战。文章涵盖了构建模拟盒子、添加溶剂离子、能量最小化、平衡模拟以及关键的轨迹分析步骤,为计算生物学和药物设计研究者提供了一套从静态对接到动态评估的完整实战指南。

weixin_29251337的博客 1219

面向对象的设计的7大原则

面向对象的设计的7大原则

伟庭的博客 1万+

Spine动画在Unity里卡顿、闪烁、排序错乱?这些性能优化与渲染问题一次讲清

本文深入解析了Spine动画在Unity中常见的卡顿、闪烁和排序错乱问题,提供了全面的性能优化与渲染解决方案。从性能瓶颈诊断到材质合并、动态合批优化,再到层级错乱与Alpha闪烁的处理,帮助开发者提升动画表现和运行效率。特别针对Unity和Spine的协同工作进行了详细的技术探讨。

weixin_29967445的博客 382

开放-封闭原则(The Open-Closed Principle)

开放-封闭原则(The Open-Closed Principle)

一朝风月 2644

实战复盘:一次绕过WAF的EDUSRC SQL注入漏洞挖掘

本文详细复盘了一次针对教育行业网站的SQL注入漏洞挖掘实战。通过手动信息收集发现可疑点,并利用‘+’号替换空格等技巧,成功绕过WAF(Web应用防火墙)的拦截。文章逐步演示了从判断注入点到手工获取数据结构、最终解密进入后台的完整过程,并总结了手工测试的优势及高级绕过思路,强调了在EDUSRC等授权范围内进行安全测试的重要性。

weixin_28622215的博客 191

手把手教你用Simulink搭建交流异步电机矢量控制模型(附完整仿真文件)

本文提供了一份详细的Simulink仿真指南,手把手教你从零开始搭建交流异步电机矢量控制模型。内容涵盖主电路搭建、坐标变换实现、双闭环PI调节器设计、转子磁链观测器调试等核心步骤,并附有完整的仿真文件,帮助读者跨越理论到实践的鸿沟,掌握高性能电机控制系统的建模与仿真技能。

pz890123的博客 670

设计原则之一:开放封闭原则

设计原则之一:开放封闭原则

zhouguizhi 6229

JavaScript China城市联动

中国全城市的地址省,市,县 <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title></title> <script src="jquery.js"></script> <script src="json.js"></...

唯唯同学 2241

开放封闭原则(Open Closed Principle)

在面向对象的设计中有很多流行的思想,比如说 “所有的成员变量都应该设置为私有(Private)”,“要避免使用全局变量(Global Variables)”,“使用运行时类型识别(RTTI:Run Time Type Identification,例如 dynamic_cast)是危险的” 等等。那么,这些思想的源泉是什么?为什么它们要这样定义?这些思想总是正确的吗?本篇文章将介绍这些思想的基础:开放封闭原则(Open Closed Principle)。 Ivar Jacobson 曾说过 “所有系统在其

u010001360的博客 1420

基于GIS的生态安全网络格局构建(附练习数据下载)

基于GIS的生态安全网络格局构建(附练习数据下载)

qq_43173805的博客 3124

深入解析FPGA中的GTX高速收发器架构与设计原理

本文深入解析了FPGA中GTX高速收发器的核心架构与设计原理。文章将GTX比作数据“高速公路”,详细拆解了其PMA(物理媒介适配层)与PCS(物理编码子层)的双层结构,阐述了串并转换、时钟恢复等关键技术,并提供了时钟源选型(QPLL/CPLL)、上电复位流程及信号完整性调试等实战指南,是掌握高速接口设计的必备知识。

f6g7h8i9j的博客 219

面向对象五大基本原则

简而言之,接口隔离原则要求将庞大的接口拆分成更小的、更具体的接口,以避免接口过于臃肿和不必要的依赖关系。它通过将不同的职责分离到不同的类中,提高了代码的可读性、可维护性和可扩展性,并降低了系统的耦合性。遵循开放封闭原则可以提高代码的可维护性和可扩展性,降低系统的耦合性,是构建高质量、可维护的软件系统的重要原则之一。同时,通过扩展现有的代码,可以实现新功能,而不会对已有的代码进行破坏性的修改。里氏替换原则的核心思想是,任何基类的实例都可以在程序中被其子类的实例替换,而不会影响程序的正确性。

qq_39939541的博客 6508

Codex入门10-Goal自主任务(进阶必学:设定目标就不管了,AI自己干活到完成)

/goal 是Codex CLI最强大的进阶功能——设定一个目标,AI就会制定计划、分步执行、自我测试、持续迭代,即使你关掉终端也会继续。本文详解/goal的工作原理、配置启用方法、常用命令(pause/resume/status/clear),以及如何写出高质量的目标描述让AI高效自主完成任务。

yueyeguzhuo的专栏 456

C++面向对象的五大原则

一:什么是面向对象 面向对象(Object Oriented,OO)是软件开发方法。面向对象的概念和应用已超越了程序设计和软件开发,扩展到如数据库系统、交互式界面、应用结构、应用平台、分布式系统、网络管理结构、CAD技术、人工智能等领域。面向对象是一种对现实世界理解和抽象的方法,是计算机编程技术发展到一定阶段后的产物。 二:面向对象的五大基本原则:SPR, OCP, LSP, DIP, ISP...

leikun153的博客 1591

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

C++ 编程基础(5)类与对象 | 5.8、面向对象五大原则

在软件开发领域,面向对象编程(OOP)是一种重要的编程范式,它通过封装、继承和多态等特性,提高了代码的可重用性、灵活性和可维护性。C++作为一种强大的面向对象编程语言,充分体现了这些原则。在面向对象的设计中,有五大核心原则被广泛认可和应用,它们分别是:单一职责原则(SRP)、开放封闭原则(OCP)、里氏替换原则(LSP)、接口隔离原则(ISP)和依赖倒置原则(DIP)。下面,将逐一解析这五大原则在C++中的应用。

个人技术博客 1629

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

C++中的面向对象(四大基本特征与五大原则)

面向对象的基本特点包括:抽象、封装、继承、多态。 1、抽象: 指对同一类对象的共同属性和行为进行概括,而暂时不解释部分细节,形成类或接口。 抽象包括两方面:数据抽象和过程抽象。 .数据抽象:描述某类对象的属性或状态(类的属性) 过程(代码)抽象 :描述某类对象的共有的行为特征或具有的功能(类的方法) 抽象的实现:类 2、封装: 指将抽象出的数据、代码封装在一起,形成类。 目的:增强安全性和简化编程,使用者不必了解具体的实现细节,而值需要通过外部接口,以特定的访问权限,来使用类的成员 3、继承: 指在已有类的

Vergesson 2589

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

C++概述

C++详解参考 参考 1、C++入门教程,C++基础教程

天道酬勤 3409

面向对象思想

很多人刚学C++核心编程的时候或者学习Java的时候一定会有一个疑问** 面向对象思想到底是个啥啊? 面向对象到底有啥用啊? 我咋样写代码才是面向对象思想啊? 我们刚接触的C语言是面向过程的思想语言,我们可以很直观的就能看懂每一条代码执行的过程。而面向对象中我们到底该如何去理解和编写? 面向对象到底是个啥 引用了知乎的一篇文章来理解什么是面向对象 抛开表象看本质。从本质概念上讲,面向对象大致有两个层次的内涵1: 要了解面向对象可以首先了解一下抽象和具象的概念,这样就可以很轻松的了解什么是面向对象了

liu010125的博客 836

面向对象相关-这一篇全了解

1、什么是面向对象,什么是面向过程。面向对象的三大基本特征和五大基本原则是什么? 解: 什么是面向过程? 把问题分解成一个一个步骤,每个步骤用函数实现,依次调用即可。就是说,在进行面向过程编程的时候,不需要考虑那么多,上来先定义一个函数,然后使用各种诸如if-else、for-each等方式进行代码执行。最典型的用法就是实现一个简单的算法,比如实现冒泡排序。(自己在家做饭) 什么是面向对象...

Franco的博客 609

C++基础——面向对象的三大特性:封装、继承、多态

封装是面向对象编程中的把数据和操作数据的函数绑定在一起的一个概念,这样能避免受到外界的干扰和误用,从而确保了安全。数据封装引申出了另一个重要的 OOP 概念,即数据隐藏。数据封装是一种把数据和操作数据的函数捆绑在一起的机制,数据抽象是一种仅向用户暴露接口而把具体的实现细节隐藏起来的机制。C++ 通过创建类来支持封装和数据隐藏(public、protected、private)。我们已经知道,类包含私有成员(private)、保护成员(protected)和公有成员(public)成员。

Volador的博客 833

【C++】C++类和对象

面向过程:将解决问题的过程视为一系列步骤的集合,按照步骤顺序逐步实现,主要关注的是实现过程和函数调用。举例:大象装进冰箱需要几步?打开冰箱门把大象放进去关闭冰箱门std::cout

qq_74326574的博客 873

面向对象设计:SOLID 原则

SOLID 原则是面向对象设计的核心,帮助构建高内聚、低耦合的代码。C++ 实现关键点使用虚函数和纯虚接口实现多态。通过组合和依赖注入替代继承。注意内存管理(如智能指针实际开发建议:根据需求灵活权衡设计,避免过度工程化。

2302_79025454的博客 624

【知识】正反例分析面向对象的七大设计原则(超详细)

学习面向对象的设计原则有助于提升代码的可维护性、可扩展性和可复用性。这些原则帮助开发者在设计系统时减少类与类之间的耦合、增强模块的独立性,使代码更容易适应需求变化,同时降低了修改时引入错误的风险。通过遵循这些设计原则,开发者能够编写更清晰、灵活、稳定的代码,有效应对复杂的业务场景和长期的软件维护。

Conner7的博客 868

面向对象设计的五大原则(SOLID)详解

SOLID原则是面向对象设计的五大核心原则,包括:单一职责原则(SRP)要求类功能专一;开闭原则(OCP)强调扩展开放而修改关闭;里氏替换原则(LSP)确保子类可替代父类;接口隔离原则(ISP)提倡小而专的接口;依赖倒置原则(DIP)主张依赖抽象而非实现。这些原则通过代码解耦、抽象继承和接口优化,共同提升软件的可维护性、扩展性和灵活性。实际开发中应平衡应用这些原则,结合测试驱动和渐进重构,构建更健壮的面向对象系统。

qq_37907545的博客 844

OO设计原则的cpp举例

OO设计原则的cpp举例

SnailElderBro的博客 790

突破编程_C++_高级教程(面向对象编程的原则)

C++ 教程:面向对象编程的原则

突破编程 1514
上一篇: 面向对象基础知识
下一篇: 面向对象三大特性
一个不务正业的程序猿
博客等级 码龄11年 1879粉丝 563原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值