面向对象编程的三特性、七原则和六视点

一、面向对象的特性

三个基本的特性:封装、继承与多态。

1、封装
面向对象编程核心思想这一就是就是将数据和对数据的操作封装在一起.通过抽象,即从具体的实例中抽取共同的性质形成一般的概念,比如类的概念.

2、继承
继承体现了一种先进的编程模式.子类可以继承父类的属性和功能,即子类继承了父类所具有的数据和数据上的操作,同时又可以增添子类独有的数据和数据上的操作.例如,"人类"继承了"哺乳类"的属性和功能,同时又增添了人类独有的属性和功能.

3、多态
 
多态是面向对象编程的又一重要特征.有两种意义的多态(表现为方法的重写(Overriding)和重载(Overloading)) 
 一种是操作名称的多态,即有多个操作具有相同的名字,但这些操作所接收的消息类型必须不同.所谓操作名称的多态是指可以向操作传递不同消息,以便让对象根据相应的消息来产生一定的行为.

二、七大基本原则 
7大基本原则:单一职责原则SRP(Single Responsibility Principle)、开放封闭原则OCP(Open-Close Principle) 、替换原则、依赖原则(the Dependency Inversion Principle DIP) (the Liskov Substitution Principle LSP) 、接口分离原则(the Interface Segregation Principle ISP)、“迪米特”法则 、组合/聚合原则

1、单一职责原则SRP(Single Responsibility Principle)
即一个类只负责一项职责
可以降低类的复杂度,一个类只负责一项职责,其逻辑肯定要比负责多项职责简单的多;
提高类的可读性,提高系统的可维护性;
变更引起的风险降低,变更是必然的,如果单一职责原则遵守的好,当修改一个功能时,可以显著降低对其他功能的影响。
需要说明的一点是单一职责原则不只是面向对象编程思想所特有的,只要是模块化的程序设计,都适用单一职责原则。

2、开放封闭原则OCP(Open-Close Principle) 
一个模块在扩展性方面应该是开放的而在更改性方面应该是封闭的。比如:一个网络模块,原来只服务端功能,而现在要加入客户端功能,
那么应当在不用修改服务端功能代码的前提下,就能够增加客户端功能的实现代码,这要求在设计之初,就应当将服务端和客户端分开,公共部分抽象出来。

3、里氏替换原则(the Liskov Substitution Principle LSP) 
子类应当可以替换父类并出现在父类能够出现的任何地方。

4、依赖倒转原则(the Dependency Inversion Principle DIP) 
具体依赖抽象,上层依赖下层。假设B是较A低的模块,但B需要使用到A的功能,
这个时候,B不应当直接使用A中的具体类: 而应当由B定义一抽象接口,并由A来实现这个抽象接口,B只使用这个抽象接口:这样就达到
了 依赖倒置的目的,B也解除了对A的依赖,反过来是A依赖于B定义的抽象接口。通过上层模块难以避免依赖下层模块,假如B也直接依赖A的实现,那么就可能造 成循环依赖。一个常见的问题就是编译A模块时需要直接包含到B模块的cpp文件,而编译B时同样要直接包含到A的cpp文件。

5、接口分离原则(the Interface Segregation Principle ISP) 
模块间要通过抽象接口隔离开,而不是通过具体的类强耦合起来。即面向接口编程

6、“迪米特”法则
又叫最少知识原则,就是说,一个对象应当对其他对象有尽可能少的了解
① 在类的划分上,应该创建有弱耦合的类;
② 在类的结构设计上,每一个类都应当尽量降低成员的访问权限;
③ 在类的设计上,只要有可能,一个类应当设计成不变类;
④ 在对其他类的引用上,一个对象对其它对象的引用应当降到最低;
⑤ 尽量降低类的访问权限;
⑥ 谨慎使用序列化功能;
⑦ 不要暴露类成员,而应该提供相应的访问器(属性)。

7、组合/聚合原则

  继承是一种强耦合的结构,父类变,子类就必须要变。“合成/聚合复用原则”:尽量使用合成/聚合,尽量不要使用类继承。它的好处是:优先使用对象的合成/聚合将有助于我们保持每个类被封装,并被集中在单个任务上。这样的类和类继承层次会保持较小规模,并且不太可能增长成为不可控制的庞然大物。
  又叫合成复用原则。原则就是在一个新的对象里面通过关联关系(包括组合关系和聚合关系)使用一些已有的对象,使之成为新对象的一部分,新对象通过委派调用已有对象的方法达到复用其已有功能的目的。也就是,要尽量使用类的合成复用,尽量不要使用继承。

就是在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分,新的对象通过向这些对象的委派达到复用已有功能的目的。这个原则有一个简短的描述:要尽量使用合成、聚合,尽量不要使用继承。

1)  新对象存取成分对象的唯一方法是通过成分对象的接口

2)  这种复用是黑箱复用,因为成分对象的内部细节是新对象所看不到的

3)  这种复用可以在运行时间内动态进行,新对象可以动态的引用与成分对象类型相同的对象

4)  合成、聚合可以应用到任何环境中去,而继承只能应用到一些有限环境中去

5)  导致错误的使用合成、聚合与继承的一个常见原因是错误的把“Has-a”关系当作“Is-a”关系。如果两个类是“Has-a”关系那么应使用合成、聚合,如果是“Is-a”关系那么可使用继承

在面向对象设计中,可以通过两种基本方法在不同的环境中复用已有的设计和实现,即通过组合/聚合关系或通过继承。

1)   继承复用:实现简单,易于扩展。破坏系统的封装性,从基类继承而来的实现是静态的,不可能在运行时发生改变,没有足够的灵活性;只能在有限的环境中使用。(“白箱”复用 )

2)   组合/聚合复用:耦合度相对较低,选择性地调用成员对象的操作;可以在运行时动态进行。(“黑箱”复用 )

组合/聚合可以使系统更加灵活,类与类之间的耦合度降低,一个类的变化对其他类造成的影响相对较少,因此一般首选使用组合/聚合来实现复用;

其次才考虑继承,在使用继承时,需要严格遵循里氏代换原则,有效使用继承会有助于对问题的理解,降低复杂度,而滥用继承反而会增加系统构建和维护的难度以及系统的复杂度,因此需要慎重使用继承复用。

三、六大视点

 复用(Reusibility) 扩展(Extensibility) 分离(Separability) 变化(Change) 简约(Simplicity) 一致(Coherance)
时间: 2024-10-06 13:45:42

面向对象编程的三特性、七原则和六视点的相关文章

面向对象编程的三个特性理解

面向对象编程的三大特性是 封装.继承.多态. 封装:是指对象把自己的数据和对数据的操作封装在了一起: 继承:是指子类对父类的继承,子类把父类的数据和对数据的操作继承了过来,同时又增添了自己的数据和对数据的操作: 多态:主要有两种类型的多态.一种是操作的名称的多态,即多个操作的名称一样,但接受的消息类型必须不同:另一种是与继承相关的多态,来自不同类型的对象对同一操作的调用产生不同的效果. 原文地址:https://www.cnblogs.com/zengfanye/p/9393524.html

Python 编程核心知识体系-模块|面向对象编程(三)

模块 面向对象编程

Javascript面向对象编程(三):非构造函数的继承

作者: 阮一峰 日期: 2010年5月24日 这个系列的第一部分介绍了"封装",第二部分介绍了使用构造函数实现"继承". 今天是最后一个部分,介绍不使用构造函数实现"继承". 一.什么是"非构造函数"的继承? 比如,现在有一个对象,叫做"中国人". var Chinese = { nation:'中国' }; 还有一个对象,叫做"医生". var Doctor ={ career:'医生

Python面向对象编程(三)

封装 1.为什么要封装? 封装就是要把数据属性和方法的具体实现细节隐藏起来,只提供一个接口.封装可以不用关心对象是如何构建的 2.封装包括数据的封装和函数的封装,数据的封装是为了保护隐私,函数的封装是为了隔离复杂度 3.数据的封装就是在属性前面加一个__ class People: def __init__(self,name,age,salary): self.name=name self.age=age self.__salary=salary p=People('zhang',19,100

【转】Javascript面向对象编程(三):非构造函数的继承

原文链接:http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_inheritance_continued.html 作者: 阮一峰 这个系列的第一部分介绍了"封装",第二部分介绍了使用构造函数实现"继承". 今天是最后一个部分,介绍不使用构造函数实现"继承". 一.什么是"非构造函数"的继承? 比如,现在有一个对象,叫做"中国人"

Javascript面向对象编程(三) --- 非构造函数的继承

一.什么是"非构造函数"的继承? 比如,现在有一个对象,叫做"中国人". var Chinese = { nation:'中国' }; 还有一个对象,叫做"医生". var Doctor ={ career:'医生' } 请问怎样才能让"医生"去继承"中国人",也就是说,我怎样才能生成一个"中国医生"的对象? 这里要注意,这两个对象都是普通对象,不是构造函数,无法使用构造函数方法实现&q

Javascript面向对象编程(三):非构造函数的继承 by 阮一峰

今天是最后一个部分,介绍不使用构造函数实现"继承". 一.什么是"非构造函数"的继承? 比如,现在有一个对象,叫做"中国人". var Chinese = { nation:'中国' }; 还有一个对象,叫做"医生". var Doctor ={ career:'医生' } 请问怎样才能让"医生"去继承"中国人",也就是说,我怎样才能生成一个"中国医生"的对象? 这里

使用Java实现面向对象编程——第三章 多态

1.多态:(polymorphism): 是具有表现多种形态能力的特征: (专业化的说法:)同一个实现接口(引用类型),使用不同的实例而执行不同的操作 指一个引用(类型)在不同情况下的多种状态.也可以理解成:多态是指通过指向父类的指针,来调用在不同子类中实现的方法. 多态是同一个行为具有多个不同表现形式或形态的能力, 多态就是同一个接口,使用不同的实例而执行不同操作,多态性是对象多种表现形式的体现. 多态的优点: 1. 消除类型之间的耦合关系 2. 可替换性 3. 可扩充性 4. 接口性 5.

《C++ Primer》之面向对象编程(三)

继承情况下的类作用域 在继承情况下,派生类的作用域嵌套在基类作用域中.如果不能在派生类作用域中确定名字,就在外围基类作用域中查找该名字的定义.正是这种类作用域的层次嵌套使我们能够直接访问基类的成员,就好象这些成员是派生类成员一样.如果编写如下代码: Bulk_item bulk; cout << bulk.book(); 名字 book 的使用将这样确定:bulk 是 Bulk_item 类对象,在 Bulk_item 类中查找,找不到名字 book:因为从 Item_base 派生 Bulk