c++ 面向对象设计五大原则

面向对象设计(OOD)是面向对象编程(OOP)必不可少的一个环节,只有好的设计,才能保障程序的质量。面向对象设计的主要任务就是类的设计,不少面向对象(OO)的先驱和前辈已经提出了很多关于类的设计原则,用于指导OOP,其中就包括类设计的五项基本原则。

1.单一职责原则(Single Resposibility Principle,SRP)

专注是一个人的优良品质,同样,单一职责也是一个类的优良设计。单一职责的核心思想:一个类只做好一件事情。

单一职责原则可以看作是高内聚、低耦合在面向对象原则上的引申。类的职责过多,容易导致类间职责依赖,提高耦合度,降低内聚性。通常意义下的单一职责,指的是类只有一种单一功能,不要为类设计过多的功能,交杂不清的功能会使代码杂乱,提高程序开发的难度和系统出错的概率,降低系统的可维护性。

要举个体现单一职责原则的最常见的例子无疑就是STL中的迭代器的设计。有些人觉得容器跟迭代器的分离是不好的设计,觉得增加了复杂度,不如直接把迭代器放在容器里更为简洁。不过很多人还是不这样认为,因为类的数量越多并不代表就越复杂,另外迭代器如果放到容器里面,就会暴露容器的一些内部结构,不太符合封装的思想。还有就是可扩展性的问题,因为对容器的访问遍历会有多种需求,如果把迭代器隔离开来你可以不修改容器类,再定义些特制的迭代器就行了,这样不管有什么奇怪的需求只要写个对应的迭代器出来就行了。

2.开放封闭原则(Open Closed Principle,OCP)

开闭原则指的是开放封闭原则,即对扩展开放,对修改封闭。

所谓修改封闭,就是之前设计好的类,不要去修改。比如删除掉一个成员函数、改变成员函数的形参列表或更改数据成员类型等。实现对修改封闭,关键在于抽象化。对一个事物抽象化,实质上是对一个事物进行概括、归纳、总结,将其本质特征抽象地用一个类来表示,这样类才会相对稳定,无需更改。

所谓扩展开放,就是在不改变已存在的类的前提下可以添加很多功能。一般是通过继承和多态来实现,如此一来,可以保持父类的原样,只需在子类中添加些所需的新功能。

“需求总是变化的”,如果遵循开放封闭原则,合理设计就能封闭变化,使类能够灵活的扩展所需的功能。

3.里氏替换原则(Liskov Substituion Principle,LSP)

Liskov替换原则指的是:子类可以替换父类并出现在父类能够出现的任何地方。这个原则是Liskov于1987年提出,它同样可以从Bertrand Meyer的DBC(Design by Contract,按契约设计)的概念推出。

C++语言机制将类的抽象与多态建立在继承的基础上,其实现的方法是面向接口编程:通过提取纯虚类(Abstract Class),将公共部分抽象为基类接口或由子类重写覆盖基类方法来达到多态的目的。Liskov替换原则的作用就是为了保证继承复用的可靠。

下面来举个违反替换原则的特殊例子:
 正方形与长方形的问题也是属于“圆不是椭圆”这类问题。我们知道正方形是一个特殊的长方形,所以可以设计两个类,正方形类继承自长方形类。长方形类有两个成员变量,分别表示长和宽,有个计算面积的成员函数。假如计算面积的方法是virtual的,这样能实现多态。在先设定长和宽后再调用计算面积的方法。我们知道正方形是长和宽相等的,如果设定长和宽的时候不是一样的,然后调用了正方形的面积计算公式,这样肯定就错了。你可能会问咋这么扯蛋啊,为啥把长和宽设成不一样啊。很多设计思想和方法是一来为了方便,二来为了让用户少犯错误,就是不管你怎么使用都不会出错,要出错应该是在编译时出错,放置运行时出错。如果出现上面说的情况编译器是没法让你知道出错了的。

所以一个正方形类继承自长方形类的设计是不好的(注意的一点是你违反了Liskov替换原则并不是说就写的代码就会出错,只是说设计不太合理。实际上你这样设计代码没准可以正常的跑得很好呢,如果没有出现一些特殊情况可能是一点bug也没有,只不过设计不合理为导致一些安全隐患而已)。

4. 依赖倒置原则(Dependecy Inversion Principle,DIP)

其核心思想是:依赖于抽象。具体而言就是高层模块不依赖于底层模块,二者都依赖于抽象;抽象不依赖于具体,具体依赖于抽象。依赖倒置原则是对传统过程性设计方法的“倒转”,是高层次模块复用及其可维护性的有效规范。

依赖一定存在于类与类、模块与模块之间。类与类之间产生依赖时,依赖倒置原则的理解可以描述如下:依赖就是刚开始时具体细节间互相依赖,我们将实现的细节变成抽象类,降低类间耦合度。然后有了抽象类,继承自它的实现类也要依赖它。那倒置两字咋理解呢? 一般情况我们是先关注细节,然后根据细节抽象出来一些概括的方法,所以按常理一般是抽象要依赖于细节的,而现在是是倒过来了,确定一个抽象类后,那些细节的实现得以抽象出来的方法为基准,变成了细节依赖于抽象了,不然你要继承了一个抽象类,你不完全实现它的方法的话可不让你实例化对象的啊。

当两个模块之间存在紧密的耦合关系时,最好的方法就是分离接口和实现:在依赖之间定义一个抽象的接口,供高层模块调用,底层模块实现接口的定义,从而有效控制耦合关系,达到依赖于抽象的设计目的。

依赖于抽象就是不对实现编程,而对接口编程。依赖于抽象是一个通用原则,而有些时候依赖于细节是在所难免的,我们需要根据具体情况在在抽象与具体之间进行取舍。

5.接口分离原则(Interface Segregation Principle,ISP)

该原则的核心思想是:使用多个小的专门的接口,而不要使用一个大的总接口。具体而言,接口应该是内聚的,应该避免“胖”接口。一个类对另一个类的依赖应该建立在最小的接口上,而不要强迫依赖不同的方法,这是一种接口污染。

其实简单点的讲与前面说的单一职责类似,这里的接口不是函数接口,而是一个类。C#中的有专门的接口interface,和类区分开来,而且C#中不像C++支持类的多继承,只支持接口的多继承,所以这里可以把接口理解成功能更小更特殊的类,一个接口可能就只要那么几个很少的方法就OK了。

接口分离手段主要有以下两种方式:
 (1)利用委托分离接口;
 (2)利用多重继承分离接口。

6.小结

概括地讲,面向对象设计原则仍然是面向对象思想的体现。例如,
 (1)单一职责原则要求类只负责一件事情。接口分离原则,让客户只关心他们所需的接口。单一职责原则与接口分离原都体现了内聚的思想;
 (2)开放封闭原则,要求类不作修改而能够扩展功能,体现了类的封装与继承;
 (3)Liskov替换原则,要求派生类要能够替换基类,是对类继承的规范;
 (4)依赖倒置原则,要求类依赖于抽象,而不是实现,是抽象思想的体现。

上面五条面向对象设计原则,可以帮助我们设计出代码易于复用、功能易于扩展、运营易于维护的程序,需要我们在实践中遵守。

以上就是c++ 面向对象设计五大原则的详细内容,更多关于c++ 面向对象设计的资料请关注我们其它相关文章!

(0)

相关推荐

  • 用C++面向对象的方式动态加载so的方法

    这几天在写一个server,由于框架相同,仅仅是获取数据源的地方有区别,所以,研究了一下如何使用面向对象的方法来动态加载so. 主要思想就是: 1.通过一个函数能够获得一个基类的指针,这样在调用基类的函数的时候,就能自动调用子类的实现了. 2.存储so对象的指针应该是外层类的一个static变量. 详细还是看代码吧: 1)首先定义一个公共的头文件,里面存储的基类的定义:(需要注意的就是,只要不是纯虚函数,那么就一定要有实现:还有就是析构函数需要为虚函数) so和主调程序都需要包含这个头文件. s

  • C++面向对象实现五子棋小游戏

    尽量将面向对象的思想融入进程序中 ChessBoard.h //ChessBoard.h #pragma once #define ROW 15 #define COL 15 #include<iostream> using namespace std; class ChessBoard//棋盘类 { public: char m_cSquare[ROW][COL]; public: ChessBoard(); void show(); }; ChessBoard.cpp //ChessBoa

  • 剖析C++的面向对象编程思想

    面向对象的程序设计 面向对象编程(Object Oriented Programming,OOP,面向对象程序设计) 的主要思想是把构成问题的各个事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙一个事物在整个解决问题的步骤中的行为. 面向过程就是分析出解决问题所需要的步骤,然后用函数逐步实现,再依次调用就可以了. 面向对象和面向过程是两种不同的编程思想,没有哪一种绝对完美,要根据具体需求拟定开发方案.例如,开发一个小型软件或应用程序,工程量小,短时间内即可完成,完全可以采用面

  • C++面向对象之多态的实现和应用详解

    前言 本文主要给大家介绍的是关于C++面向对象之多态的实现和应用的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 多态 大家应该都听过C++三大特性之一多态,那么什么多态呢?多态有什么用?通俗一点来讲-> 多态性可以简单地概括为"一个接口,多种方法",程序在运行时才决定调用的函数,它是面向对象编程领域的核心概念.当多态应用形参类型的时候,可以接受更多的类型.当多态用于返回值类型的时候,可以返回更多类型的数据.多态可以让你的代码拥有更好的扩展性. 多态分

  • 分享一下8年C++面向对象设计的经验体会

    六年前,我刚热恋"面向对象"(Object-Oriented)时,一口气记住了近十个定义.六年后,我从几十万行程序中滚爬出来准备写点心得体会时,却无法解释什么是"面向对象",就象说不清楚什么是数学那样.软件工程中的时髦术语"面向对象分析"和"面向对象设计",通常是针对"需求分析"和"系统设计"环节的."面向对象"有几大学派,就象如来佛.上帝和真主用各自的方式定义了这个

  • 关于C++面向对象设计的访问性问题详解

    前言 最近在看Scott Meyers大神的<Effective C++>和<More Effective C++>,虽然这两本书都是古董级的教参了(当然针对C++11/C++14作者所更新的<Modern Effective C++>英文已经发售了,不过还没中文翻译版本),但是现在看来仍然收益匪浅,而且随着对这个复杂语言了解的深入和实践项目经验的增加,很多东西和作者产生了一种共鸣,以前种种疑惑突然有种拨云雾而见天日.豁然开朗的感觉,也难怪被列为合格C++程序员之必读书

  • c++ 面向对象的类设计

    类的设计在于用恰到好处的信息来完整表达一个职责清晰的概念,恰到好处的意思是不多也不少,少了,就概念就不完整:多了,就显得冗余,累赘,当然特例下,允许少许的重复,但是,这里必须要有很好的理由.冗余往往就意味着包含了过多的信息,概念的表达不够精准,好比goto,指针,多继承这些货色,就是因为其过多的内涵,才要严格限制其使用.好像,more effective c++上说的,class的成员函数,应该是在完整的情况下保持最小化.但是,这里我们的出发点,是成员数据的完整最小化. 最小化的好处是可以保持概

  • c++ 面向对象设计五大原则

    面向对象设计(OOD)是面向对象编程(OOP)必不可少的一个环节,只有好的设计,才能保障程序的质量.面向对象设计的主要任务就是类的设计,不少面向对象(OO)的先驱和前辈已经提出了很多关于类的设计原则,用于指导OOP,其中就包括类设计的五项基本原则. 1.单一职责原则(Single Resposibility Principle,SRP) 专注是一个人的优良品质,同样,单一职责也是一个类的优良设计.单一职责的核心思想:一个类只做好一件事情. 单一职责原则可以看作是高内聚.低耦合在面向对象原则上的引

  • PHP面向对象五大原则之接口隔离原则(ISP)详解

    本文实例讲述了PHP面向对象五大原则之接口隔离原则(ISP).分享给大家供大家参考,具体如下: 设计应用程序的时候,如果一个模块包含多个子模块,那么我们应该小心对模块做出抽象.设想该模块由一个类实现,我们可以把系统抽象成一个接口.但是要添加一个新的模块扩展程序时,如果要添加的模块只包含原系统中的一些子模块,那么系统就会强迫我们实现接口中的所有方法,并且清寒要编写一些哑方法.这样的接口被称为肚胖接口或者被污染的接口,使用这样的接口将会给系统引入一些不当的行为,这些不当的行为可能导致不正确的结果,也

  • PHP面向对象五大原则之开放-封闭原则(OCP)详解

    本文实例讲述了PHP面向对象五大原则之开放-封闭原则(OCP).分享给大家供大家参考,具体如下: 1. 什么是"开放-封闭" 随着软件系统规模的不断增大,软件系统的维护和修改的复杂性不断提高,这种困境促使法国工程院士Bertrand Meyer在1998年提出了"开放-封闭"(Open-Close Principle,OCP)原则,这条原则的基本思想是: Open(Open for extendtion)模块的行为必须是开放的.支持扩展的,而不是僵化的. Close

  • PHP面向对象五大原则之单一职责原则(SRP)详解

    本文实例讲述了PHP面向对象五大原则之单一职责原则(SRP).分享给大家供大家参考,具体如下: 单一职责原则(Single Pesponsibility Principle, SRP) 单一职责有两个含义: 一个是避免相同的职责分散到不同的类中, 别一个是避免一个类承担太多职责 为什么要遵守SRP呢? (1)可以减少类之间的耦合 如果减少类之间的耦合,当需求变化时,只修改一个类,从而也就隔离了变化:如果一个类有多个不同职责,它们耦合在一起,当一个职责发生变化时,可能会影响到其他职责. (2)提高

  • PHP面向对象五大原则之依赖倒置原则(DIP)详解

    本文实例讲述了PHP面向对象五大原则之依赖倒置原则(DIP).分享给大家供大家参考,具体如下: 什么是依赖倒置呢?简单地讲就是将依赖关系倒置为依赖接口,具体概念如下: 1.上层模块不应该依赖于下层模块,它们共同依赖于一个抽象(父类不能依赖子类,它们都要依赖于抽象类) 2.抽象不能依赖于具体,具体应该要依赖于抽象. 注意,这里的接口不是狭义的接口. 为什么要依赖接口?因为接口体现对问题的抽象,同时由于抽象一般是相对稳定的或者是相对变化不频繁的,而具体是易变的.因此依赖抽象是实现代码扩展和运行期内绑

  • PHP面向对象五大原则之里氏替换原则(LSP)详解

    本文实例讲述了PHP面向对象五大原则之里氏替换原则(LSP).分享给大家供大家参考,具体如下: 替换原则由MIT计算机科学实验室的Liskov女士在1987年的OOPSLA大会上的一篇文章中提出,主要阐述有关继承的一些原则,故称里氏替换原则. 2002年,Robert C.Martin出版了一本名为<Agile Software Development Principles Patterns and Practices>的书,在书中他把里氏替换原则最终简化成一句话:"Subtypes

  • C#面向对象设计的七大原则

    本文我们要谈的七大原则,即:单一职责,里氏替换,迪米特法则,依赖倒转,接口隔离,合成/聚合原则,开放-封闭 . 1.   开闭原则(Open-Closed Principle, OCP) 定义:软件实体应当对扩展开放,对修改关闭.这句话说得有点专业,更通俗一点讲,也就是:软件系统中包含的各种组件,例如模块(Modules).类(Classes)以及功能(Functions)等等,应该在不修改现有代码的基础上,去扩展新功能.开闭原则中原有"开",是指对于组件功能的扩展是开放的,是允许对其

  • 10个Java程序员熟悉的面向对象设计原则

    面向对象设计原则是OOPS编程的核心, 但我见过的大多数Java程序员热心于像Singleton (单例) . Decorator(装饰器).Observer(观察者) 等设计模式,而没有把足够多的注意力放在学习面向对象的分析和设计上面.学习面向对象编程像"抽象"."封装"."多态"."继承" 等基础知识是重要的,但同时为了创建简洁.模块化的设计,了解这些设计原则也同等重要.我经常看到不同经验水平的java程序员,他们有的不知

  • java面向对象设计原则之开闭原则示例解析

    概念 唯一不变的是不断的变化,在软件开发中应该对需求的变化持开放态度,我们要做的就是如何将这种变化对我们现有的成果带来最小的冲击.开闭原则直接面对面向对象程序的目标扩展性和可维护性,要求对扩展开放,对修改关闭:即在不修改原有代码的情况下改变模块的行为.该原则是面向对象程序设计的总原则,也是度量程序设计的好与坏的唯一标准 实现 开闭原则的实现策略主要在面向对象的封装性和多态性的基础上,利用面向对象的其他原则完成的. 1.使用多态机制解决问题. 如:远程监控系统使用数据传输使用427版本的协议,一年

  • java面向对象设计原则之里氏替换原则示例详解

    目录 概念 实现 拓展 概念 里氏替换原则是任何基类出现的地方,子类一定可以替换它:是建立在基于抽象.多态.继承的基础复用的基石,该原则能够保证系统具有良好的拓展性,同时实现基于多态的抽象机制,能够减少代码冗余. 实现 里氏替换原则要求我们在编码时使用基类或接口去定义对象变量,使用时可以由具体实现对象进行赋值,实现变化的多样性,完成代码对修改的封闭,扩展的开放.如:商城商品结算中,定义结算接口Istrategy,该接口有三个具体实现类,分别为PromotionalStrategy (满减活动,两

随机推荐