02 Android常见设计模式:面向对象的设计原则

一. 类的设计原则

  • 开闭原则
  • 里氏替换原则
  • 迪米特法则(最少知道原则)
  • 单一职责原则
  • 接口隔离原则
  • 依赖倒置原则

这几个设计原则之间并不是相互孤立的,彼此间存在着一定关联,一个可以是另一个原则的加强或是基础。违反了其中的某一个,可能同时违反了其余的原则。

开闭原则是面向对象的可复用设计的基石,其他设计原则是实现开闭原则的手段和工具。

一般地,我们可以把这六个原则分为以下2个部分:

设计目标: 开闭原则 、里式替换原则、迪米特法则
设计方法: 单一职责原则 、接口隔离原则、依赖倒置原则

1. 开闭原则

定义:

一个软件实体应当 对扩展开放,对修改关闭。在程序需要进行新增功能的时候,不能去修改原有的代码,应该尽量通过扩展的方式来实现变化。也就是说在设计一个模块的时候,应当使这个模块可以在不被修改的前提下被扩展,即实现在不修改源代码的情况下改变这个模块的行为。

举例:

就像插座一样,可以给很多不同的电器充电,但是却不需要改变插座本身,我们只需提前把插头的规格定义好。这样做的好处也很明显,使得程序的扩展性好,易于维护和升级。

2. 里氏替换原则

定义:

所有引用父类的地方必须能透明地使用其子类的对象。

分析:

  • 在软件中如果能够使用基类对象,那么一定能够使用其子类对象。把基类都替换成它的子类,程序将不会产生任何错误和异常,反过来则不成立。如果一个软件实体使用的是一个子类的话,那么它不一定能够使用基类。
  • 里式替换原则是实现开闭原则的重要方式之一,由于使用基类对象的地方都可以使用子类对象,因此在程序中尽量使用基类类型来对对象进行定义,而在运行时再确定其子类类型,用子类对象来替换父类对象。

举例:

正好今天去吃小龙虾,那就说说虾,它是一种食品。虾的衍生类很多有南极红虾、青虾、河虾、草虾、对虾、明虾、龙虾等,如果衍生类替换了基类的原本方法,如把食品改成了体育用品(那么软件的基本功能受到影响),就不符合里氏代换原则。

总结:

子类型必须能够替换掉它们的父类型。

3. 迪米特法则

定义:

又叫最少知道原则,一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。

分析:

迪米特法则就是指一个软件实体应当尽可能少的与其他实体发生相互作用。这样,当一个模块修改时,就会尽量少的影响其他的模块,扩展会相对容易,这是对软件实体之间通信的限制,它要求限制软件实体之间通信的宽度和深度。

举例:

智能音箱,只需要把指令告诉智能音箱,智能音箱就会识别指令去调用各种已链接的电器,如:我要看湖南卫视,把空调温度低一点,扫地机器人开启清扫,等等。智能音箱帮我们解决了要找很多遥控器的烦恼。好处是降低类之间的耦合,减少对其他类的依赖。

4. 单一职责原则

定义:

一个对象应该只包含单一的职责,并且该职责被完整地封装在一个类中。且就一个类而言,应该仅有一个引起它变化的原因。

分析:

  • 一个类(或者大到模块,小到方法)承担的职责越多,它被复用的可能性越小,而且如果一个类承担的职责过多,就相当于将这些职责耦合在一起,当其中一个职责变化时,可能会影响其他职责的运作。
  • 类的职责主要包括两个方面:数据职责和行为职责,数据职责通过其属性来体现,而行为职责通过其方法来体现。
  • 单一职责原则是实现高内聚、低耦合的指导方针,在很多代码重构手法中都能找到它的存在,它是最简单但又最难运用的原则,需要设计人员发现类的不同职责并将其分离,而发现类的多重职责需要设计人员具有较强的分析设计能力和相关重构经验。

举例:

就像一家公司,团队中每个人都分工明确。有产品经理,项目经理,技术经理,QA经理等等。

5. 接口隔离原则

定义:

客户端不应该依赖那些它不需要的接口。一旦一个接口太大,则需要将它分割成一些更细小的接口,使用该接口的客户端仅需知道与之相关的方法即可。

分析:

  • 接口隔离原则是指使用多个专门的接口,而不使用单一的总接口。每一个接口应该承担一种相对独立的角色,不多不少,不干不该干的事,该干的事都要干。
  • 使用接口隔离原则拆分接口时,首先必须满足单一职责原则,将一组相关的操作定义在一个接口中,且在满足高内聚的前提下,接口中的方法越少越好。
  • 可以在进行系统设计时采用定制服务的方式,即为不同的客户端提供宽窄不同的接口,只提供用户需要的行为,而隐藏用户不需要的行为。

举例:

假设要设计操控机器人的接口,不能只有行动和停止的接口,行动可以拆分成前进,后退,转向,跳跃,等等,接口拆分可以使组合更多。

6. 依赖倒置原则

定义:

  • 高层模块不应该依赖低层模块,它们都应该依赖抽象。抽象不应该依赖于细节,细节应该依赖于抽象。

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

举例:

以电脑为例,无论主板、CPU、内存、硬件都是在针对接口设计的,如果出现某个局部的配件坏了就只要替换对应的配件就行了。如果针对实现来设计,那么电脑显示屏坏了就需要把主机也一并换掉。

总结:

高层模块不应该依赖底层模块,两个都应该依赖与抽象;抽象不应该依赖于细节,细节应该依赖于抽象。

二. 结论

我们只要掌握好总体的设计原则,然后学习常用的设计模式就行了,实际开发中也不是每种设计模式都会经常用到。好的程序遵循的是设计原则,而非设计模式。现在就出现很多新的演变出来的模式,这些模式都是因为出现了新业务的原因,设计模式不是规范,只是一种借鉴。

你可能感兴趣的:(02 Android常见设计模式:面向对象的设计原则)