【设计模式】概述面向对象六大原则

六大原则

  • 简介
  • 1. 单一职责原则
  • 2. 开闭原则
  • 3. 里氏替换原则
  • 4. 依赖倒置原则
    • 实现压缩程序
  • 5. 接口隔离原则
  • 6. 迪米特原则

简介

设计模式的书籍并不少见,各有特色,那为何要另起炉灶?答曰:“为了更贴近实际理解,而不是应试。”

本系列采用java语言来表示,不同语言稍微有所不同,这里不再加以区分。

1. 单一职责原则

又称SRP,定义:一个类,应该有且仅有一个引起它变化的原因,换而言之,一个类的函数应该有很高的相关性,其数据也是如此。

比方说,一个用于输出的类System.out,就是由相关性很高的输出函数封装的。

注意,由于对类的职责 定义、是什么、怎么划分 每个人都有不同见解,这需要创作者自己定义。 最基本的是,但两个完全不一样的功能就不应该放在同一个类中。

2. 开闭原则

又称OCP,定义:软件中的对象(类、模块、函数等) 应该 对继承(扩展)是开放的,对修改时封闭的。,具体操作起来,也就是在软件生命周期内,因为变化、升级和维护等原因需要对软件原有代码进行维护修改时,**不应该修改原代码,而是通过扩展实现变化。**当然,这是理想化的模型,为了避免代码过于臃肿和难以理解,仍然会有修改代码的情况。

如果说,某些代码修改后会引起其它问题,只有在遵循本原则下,才能确保原有软件模块的正确性,以及尽量少影响原有模块。
典型例子是,安卓View.java已经增加到恐怖的3万多行代码,越发臃肿,现在,Compose的出现也有部分目的是为了弥补它不足。

当然,在java中,给一个类添加新的功能或者之后为其有所修改,可以通过接口来实现

3. 里氏替换原则

又称LSP,它有两种不同程度的定义:

  • 严格的说,C类型的对象,都有F类型的对象与之匹配,使得所有有T类型对象的程序在全替换时候,对程序无影响,那么可知:C是F的子类(Child是Father的子类)
  • 简单地说,所有使用父类的地方,换成子类也没问题。

打个比方,Java的Set类,你可以使用HashSet,也可以是TreeSet,这就是遵循了里氏替换原则。

里氏替换原则核心是抽象,而抽象依赖于继承,在开闭原则中,我们就谈到了继承(扩展)的优缺点:

  • 代码重用,减少创建新类成本,每个子类都有父类的方法、属性
  • 与父类相似,但有区别
  • 提高代码的可扩展性。

缺点:

  • 继承会暴露父类某些不愿意透露给子类的方法,有可入侵性。
  • 子类代码冗余,不够灵活摆脱父类方法和属性。

开闭原则和里氏替换原则是一对鸳鸯,在开发中是不离不弃的,同时他它们也共同强调了抽象这一特性。

4. 依赖倒置原则

又称DIP,依赖倒置原则 是一种特定的解耦方式:使得高层次模块不依赖于低层次的模块的实现细节的目的,依赖被颠倒了。
并且有几个关键点:

  • 高层次模块不应该依赖低层模块,两者都应该依赖其抽象。
  • 抽象不应该依赖细节
  • 细节应该依赖抽象

注意,在Java中,抽象就是 接口抽象类,他们不能实例化;细节就是实现接口、实现类或者继承抽象类而产生的新类,他们可以实例化。高层模块就是调用端底层模块就是具体实现类

由于翻译的原因,笔者更偏向于更详细描述 依赖 的意思:

  • 高层次模块不应该 依靠 低层模块 来实现目的,两者都应该依赖抽象 所指定的关系来实现
  • 抽象的关系要指明,不应该细节来决定
  • 细节应该由抽象的定义依赖关系规则来 丰富 其功能

总结:模块间的依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或者抽象类产生的。

所以说,面向接口编程,抑或面向抽象(接口、抽象类)编程,是开闭原则、** 里氏替换原则**的精髓之一。

举个例子,请看以下代码,和使用本原则后的结果。

实现压缩程序

众所周知,压缩算法有很多种,我们拟做一程序实现一个应用,默认是Zip压缩:
【设计模式】概述面向对象六大原则_第1张图片

上面省略了无关代码,假设这样写没有问题,那么现在,用户想使用7z来压缩文件,怎么办?
这时候,我们需要引入7z压缩算法,在构造函数 参数传入 选择的算法 并写好解析,然后再在输出做好决定:
【设计模式】概述面向对象六大原则_第2张图片
这样写是非常复杂的,假如再来个rar压缩呢?是不是代码无意义的增加了?假如用户想自定义呢?是是很棘手?
所以我们可以简化一下:
【设计模式】概述面向对象六大原则_第3张图片

这样,就简单多了,而且也十分灵活。

我们发现,上面几种方法,似乎抽象是让代码灵活的唯一方式。

5. 接口隔离原则

又称ISP,一种定义是:客户端不应该依赖它不需要的接口 。另一个 定义是:类间的依赖关系应该建立在最小的接口上。

也就是说,ISP是将非常庞大、臃肿的接口拆分成更小的和更具体的接口,这样客户将会只需要知道他们感兴趣的方法。

接口隔离原则目的是使得系统解开耦合,从而容易重构、更改和重新部署,也可以在调用指定接口方法而不用暴露其他方法,避免方法泄露。

Bob大叔 (Robert C Martin )在21世纪初就将上述五个原则定义为SOLID原则,足以发现他们在程序的重要性,经过学习,我们就能概括其本质:抽象、单一职责、功能尽量分化

6. 迪米特原则

又称LOD,也叫作最小知识原则(Least Knowledge Principle),定义是:一个对象对其他对象仅有最小了解。,也就是说:“一个类对自己需要耦合的或调用的类知道的最少,类内部实现和调用者无关,调用者只要知道它需要的方法就可以了。”为什么这么做?因为,类和类之间关系越密切,当一个类发生改变时,另一个极有可能改变。

举例:给多个类的数组排序,调用Arrays.sort(),而不用关心其中的算法。

你可能感兴趣的:(Java小叙,设计模式,java)