设计模式

设计模式——面向对象设计原则

Posted by Liangjf on April 9, 2019

设计模式——面向对象设计原则

1.什么是面向对象设计

世界是具体的,认知是抽象的。像自然界中的生物、植物、动物一个个名词,就是对一系列具体个体抽象出来的称谓,而鱼、老虎、树等就是一个个实在的具体。哦,也许你会说,树也是对一系列具体个体的抽象出来的称谓,对也不对,对是因为树确实是一系列具体个体的抽象称谓,不对是因为照这个逻辑下去,就会陷入死循环,直到小到细胞,原子,夸克,但是你能保证夸克就是最小的具体吗?还好前人已经帮我们解决这个思考了,通过继承的关系,可以从抽象开始,逐层的继承下去,就会形成一个具有抽象与具体关系的层次关系,就如同我们的世界那样,也是通过抽象与具体形成的层次。

面向对象的设计实质是通过对现实世界提炼出符合需求的抽象封装,然后通过逐层继承抽象并拓展实现,实现同一继承来源然而变现多态性质。

比如下图的继承关系,这是游戏的从最抽象出的对象,到角色、静态采集物、场景,再到人物、宠物、怪、坐骑等,就是典型的面向对象设计。

2.为什么需要面向对象设计

软件设计就难的是应对变化、变化、变化。通过把系统功能封装成一个个对象,就可以粒度细化、功能实现的耦合度低和职责独立,细化了就能够更好的把控;耦合度低就是高内聚、松耦合,能够减少功能实现之间的关联,降低修改的影响;职责单一独立就能够提高代码复用,复用就能够提高开发效率与提高可维护性。

为了能够更好的实现面向对象设计,应该做到隔离变化,也就是把变与不变隔离开,不要让变化的东西影响到不变的,适应软件的变化。对象各有独自的功能,也就是对象的功能要单一,新能功能类型不应该影响到旧的对象。这里说的比较简单,其实大师们已经总结出面向对象设计原则来指导我们的开发了。

3.面向对象设计原则

3.1依赖倒置原则

  • 高层模块(稳定)不应该依赖于低层模块(变化),二者都应该依赖于抽象(稳定) 。
  • 抽象(稳定)不应该依赖于实现细节(变化) ,实现细节应该依赖于抽象(稳定)。

3.2开闭原则

  • 对扩展开放,对更改封闭。
  • 类模块应该是可扩展的,但是不可修改。

3.3单一职责原则

  • 一个类应该仅有一个引起它变化的原因。
  • 变化的方向隐含着类的责任。

3.4里氏替换原则

  • 子类必须能够替换它们的基类(IS-A)。
  • 继承表达类型抽象。

3.5接口隔离原则

  • 不应强迫客户程序依赖它们不用的方法。
  • 接口应该小而完备。

3.6优先使用对象组合,而不是类继承

  • 类继承通常为白箱复用,对象组合通常为黑箱复用
  • 继承在某种程度上破坏了封装性,子类父类耦合度高。
  • 对象组合则只要求被组合的对象具有良好定义的接口,耦合度低。

3.7找出变化点,封装变化点

  • 寻找出变与不变的分割点,对二者封装,让设计者对单方面修改时不会影响到另一面。实现层次间的松耦合。

3.8面向接口编程,而不是面向对象编程

  • 不将变量类型声明为某个特定的具体类,而是声明为某个接口。
  • 客户程序无需获知对象的具体类型,只需要知道对象所具有的接口。
  • 减少系统中各部分的依赖关系,从而实现高内聚、松耦合的类型设计方案。

4.面向接口设计

在现实中,面向接口设计随处可见,比如那么多的标准协会,比如发布的C++标准,C-98/03/11等,比如各个工厂生产的零件等,都有各自对应的生产标准,只有接口标准化,才会使产业更加强盛。相反,接口没有标准,就会造成生产力低下,根本无经济全球化一说了。

面向接口编程就是抽象需求成一个个独立的接口/抽象类,然后被继承或委托/组成的形式来实现或拓展新的具体或更加强大完善的抽象,通过层层封装、继承,最后就会实现运行时多态的特性,从而提高代码的灵活性。

5.小结

本文通过分析什么是面向对象,为什么需要面向对象,和面向对象设计的原则来说明软件开发中面向对象设计是实现大型软件程序的基石。面向接口编程,而不是面向对象编程,能够使代码更加灵活,更加优美强大。