BearZPY Blog

Hi, nice to meet you

BearZPY's avatar BearZPY

面向对象设计原则

面向对象设计原则

在 程序设计领域, SOLID(单一功能、开闭原则、里氏替换、接口隔离以及依赖反转)是由罗伯特·C·马丁在 21 世纪早期引入的记忆术首字母缩略字,指代了面向对象编程和面向对象设计的五个基本原则。应对不断改变的需求就会有新的规则出现,包括迪米特原则等。

单一职责原则 SRP

单一原则的定义就是:就一个类而言,应该仅有一个引起他变化的原因,一个类中应该是一组相关性很高的函数。简单的来说就是一个类只应该负责一件事。因为单一职责的划分界限并不能总那么清晰,所以常常是靠个人经验来划分的。

eg:网络图片加载,可以分为,网络下载,图片显示,图片缓存等部分。如果写出一个类,这个类就会非常的臃肿,难以修改。所以我们需要根据具体的业务、功能对类进行相应的拆分。

开闭原则 OCP

开闭原则的定义是:软件中的对象(类,模块,函数等)应该对于扩展是开放的,对于修改是闭合的。这是 Java 世界最基础的设计原则。
类的实现只应该因错误而修改,新的或者改变的特性应该通过新建不同的类实现。应该尽量通过拓展的方式来实现变化,而不是通过修改原先的代码。我们可以使用抽象化接口来实现这个目标。开闭原则强调的是让程序更加稳定,灵活。

eg: 网络图片加载中的图片缓存功能可以包含内存缓存,磁盘缓存,或者混合缓存。他们的共性就是都有存放、读取缓存的功能,这个存放、读取的功能就可以抽象出来作为一个接口。新的缓存方式只要实现这个接口就能在原先的代码里使用。

里氏替换原则 LSP

开闭原则的定义是:派生类(子类)对象能够替换其基类(超类)对象被使用,所有引用基类的地方必须能透明的使用其子类的对象。其实还是抽象的实现。里氏替换原则强调的是让程序的拓展性更好。

eg:图片缓存功能中的内存缓存,磁盘缓存,或者混合缓存功能因为实现了读取、存放的接口,所以都可以在网络图片加载器里使用。

接口隔离原则 ISP

接口隔离原则的定义是:类应该不依赖于它不使用的方法。接口隔离原则拆分非常庞大臃肿的接口成为更小的和更具体的接口,这样客户将会只需要知道他们感兴趣的方法。目的是系统解开耦合,从而容易重构,更改和重新部署。

eg:图片缓存功能中的读取功能,无论是内存缓存还是磁盘缓存,都有自己在读取过程中使用的其他的方法,但是用户读取对这些是不关心的,他只要知道这个是可读的就可以了。

依赖反转原则 DIP

依赖反转原则指的是一种特定的解耦形式,使得高层次的模块不依赖于低层次的模块的实现细节,依赖关系被颠倒(反转),从而使得低层次模块依赖于高层次模块的需求抽象。

依赖反转原则有几个关键点:

  • 高层模块不应该依赖底层模块
  • 高层、底层模块都应该依赖于抽象需求
  • 抽象不应该依赖细节
  • 细节应该依赖抽象

Java 语言中,抽象指的是接口或者抽象类,细节就是实现抽象的类。高层模块就是调用端,底层模块就是实现类。

eg:图片加载器并不直接定义哪种缓存策略,而是定义了一个读取、存放的接口,当用户需要使用具体的缓存策略时,通过依赖注入的方式把实现了抽象接口的类,传递给网络图片加载器即可使用,保证了系统的灵活性。

迪米特原则 LKP

迪米特原则也称最少知识原则,就是说一个对象应当对其他对象有尽可能少的了解,或者说只与直接面对的人沟通。迪米特法则的初衷在于降低类之间的耦合。由于每个类尽量减少对其他类的依赖,因此,很容易使得系统的功能模块功能独立,相互之间不存在(或很少有)依赖关系。迪米特法则不希望类之间建立直接的联系。如果真的有需要建立联系,也希望能通过它的友元类来转达。因此,应用迪米特法则有可能造成的一个后果就是:系统中存在大量的中介类,这些类之所以存在完全是为了传递类之间的相互调用关系,这在一定程度上增加了系统的复杂度。

eg: 图片缓存功能里面的内存缓存,用户只需要知道使用的是内存缓存就行了,至于里面使用哪种 API,及其相关用法,对于用户来说是不需要知道的。