面向对象编程3大特性 7大原则


一、面向对象的特性

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

1、封装
面向对象编程核心思想这一就是就是将数据和对数据的操作封装在一起.通过抽象,即从具体的实例中抽取共同的性质形成一般的概念,比如类的概念.
2、继承
继承体现了一种先进的编程模式.子类可以继承父类的属性和功能,即子类继承了父类所具有的数据和数据上的操作,同时又可以增添子类独有的数据和数据上的操作.例如,"人类"继承了"哺乳类"的属性和功能,同时又增添了人类独有的属性和功能.
3、多态
 
多态是面向对象编程的又一重要特征.有两种意义的多态(表现为方法的重写(Overriding)和重载(Overloading)) 
 一种是操作名称的多态,即有多个操作具有相同的名字,但这些操作所接收的消息类型必须不同.所谓操作名称的多态是指可以向操作传递不同消息,以便让对象根据相应的消息来产生一定的行为.

二、七大基本原则 
7大基本原则:单一职责原则SRP(Single Responsibility Princ iple)、开放封闭原则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)   组合/聚合复用:耦合度相对较低,选择性地调用成员对象的操作;可以在运行时动态进行。(“黑箱”复用 )

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

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

、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

一、单一职责原则:

全称:Single-Responsibility Principle

说明:就一个类而言,应该只专注于做一件事和仅有一个引起它变化的原因。所谓职责,我们可以理解他为功能,就是设计的这个类功能应该只有一个,而不是两个或更多。也可以理解为引用变化的原因,当你发现有两个变化会要求我们修改这个类,那么你就要考虑撤分这个类了。因为职责是变化的一个轴线,当需求变化时,该变化会反映类的职责的变化。

使用SRP注意点

1、一个合理的类,应该仅有一个引起它变化的原因,即单一职责;

2、在没有变化征兆的情况下应用SRP或其他原则是不明智的;

3、在需求实际发生变化时就应该应用SRP等原则来重构代码;

4、使用测试驱动开发会迫使我们在设计出现臭味之前分离不合理代码;

5、如果测试不能迫使职责分离,僵化性和脆弱性的臭味会变得很强烈,那就应该用FacadeProxy模式对代码重构;SRP优点:消除耦合,减小因需求变化引起代码僵化。

二、里氏代换原则

全称:“Liskov Substitution Principle

说明:子类型必须能够替换它们的基类型。一个软件实体如果使用的是一个基类,那么当把这个基类替换成继承该基类的子类,程序的行为不会发生任何变化。软件实体察觉不出基类对象和子类对象的区别。

优点:可以很容易的实现同一父类下各个子类的互换,而客户端可以毫不察觉。

三、依赖倒置原则

全称:“Dependence Inversion Principle

说明:要依赖于抽象,不要依赖于具体。客户端依赖于抽象耦合。

抽象不应当依赖于细节;细节应当依赖于抽象;

要针对接口编程,不针对实现编程。

优点:使用传统过程化程序设计所创建的依赖关系,策略依赖于细节,这是糟糕的,因为策略受到细节改变的影响。依赖倒置原则使细节和策略都依赖于抽象,抽象的稳定性决定了系统的稳定性。

怎样做到依赖倒置?

以抽象方式耦合是依赖倒转原则的关键。抽象耦合关系总要涉及具体类从抽象类继承,并且需要保证在任何引用到基类的地方都可以改换成其子类,因此,里氏代换原则是依赖倒转原则的基础。

在抽象层次上的耦合虽然有灵活性,但也带来了额外的复杂性,如果一个具体类发生变化的可能性非常小,那么抽象耦合能发挥的好处便十分有限,这时可以用具体耦合反而会更好。

层次化:所有结构良好的面向对象构架都具有清晰的层次定义,每个层次通过一个定义良好的、受控的接口向外提供一组内聚的服务。

依赖于抽象:建议不依赖于具体类,即程序中所有的依赖关系都应该终止于抽象类或者接口。尽量做到:

1、任何变量都不应该持有一个指向具体类的指针或者引用。

2、任何类都不应该从具体类派生。

3、任何方法都不应该覆写它的任何基类中的已经实现的方法。

四、接口隔离原则

全称:“Interface Segregation Principle

说明:使用多个专一功能的接口比使用一个的总接口总要好。从一个客户类的角度来讲:一个类对另外一个类的依赖性应当是建立在最小接口上的。过于臃肿的接口是对接口的污染,不应该强迫客户依赖于它们不用的方法。

优点:会使一个软件系统功能扩展时,修改的压力不会传到别的对象那里。

如何实现接口隔离原则

不应该强迫用户依赖于他们不用的方法。

1、利用委托分离接口。

2、利用多继承分离接口。

五、迪米特原则

全称:Law of Demeter

说明:对象与对象之间应该使用尽可能少的方法来关联,避免千丝万缕的关系。

如何实现迪米特法则?

迪米特法则的主要用意是控制信息的过载,在将其运用到系统设计中应注意以下几点:

1) 在类的划分上,应当创建有弱耦合的类。类之间的耦合越弱,就越有利于复用。

2) 在类的结构设计上,每一个类都应当尽量降低成员的访问权限。一个类不应当public自己的属性,而应当提供取值和赋值的方法让外界间接访问自己的属性。

3) 在类的设计上,只要有可能,一个类应当设计成不变类。

4) 在对其它对象的引用上,一个类对其它对象的引用应该降到最低。

六、开放-封闭原则

全称:“Open-Closed Principle

说明:对扩展开放,对修改关闭。

优点:按照OCP原则设计出来的系统,降低了程序各部分之间的耦合性,其适应性、灵活性、稳定性都比较好。当已有软件系统需要增加新的功能时,不需要对作为系统基础的抽象层进行修改,只需要在原有基础上附加新的模块就能实现所需要添加的功能。增加的新模块对原有的模块完全没有影响或影响很小,这样就无须为原有模块进行重新测试。

如何实现“开-闭”原则?

在面向对象设计中,不允许更改的是系统的抽象层,而允许扩展的是系统的实现层。换言之,定义一个一劳永逸的抽象设计层,允许尽可能多的行为在实现层被实现。

解决问题关键在于抽象化,抽象化是面向对象设计的第一个核心本质。

对一个事物抽象化,实质上是在概括归纳总结它的本质。抽象让我们抓住最最重要的东西,从更高一层去思考。这降低了思考的复杂度,我们不用同时考虑那么多的东西。换言之,我们封装了事物的本质,看不到任何细节。

在面向对象编程中,通过抽象类及接口,规定了具体类的特征作为抽象层,相对稳定,不需更改,从而满足“对修改关闭”;而从抽象类导出的具体类可以改变系统的行为,从而满足“对扩展开放”。

对实体进行扩展时,不必改动软件的源代码或者二进制代码。关键在于抽象。




  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值