如何理解面向对象的OO设计原则和设计模式?

发布时间:2023年12月31日

一、如何理解面向对象的编程原则?

在这里插入图片描述

单一职责原则(Single Responsibility Principle)

  • 一个类,应该由一组相关性很高的数据和方法组成。
  • 一个类应该仅有一个引起它变化的原因。

单一职责最难界定的就是关于“职责”的定义,往往需要丰富的经验和对业务的认知程度,这也更加容易引起撕逼大战,似乎任何时候都可以拿它来辩论。如设计 ImageLoader 时,图片缓存功能和图片加载逻辑应该分开写在不同的类中。再比如在 Android 开发的早期 MVC 盛行,什么都往 Activity 里面加(网络请求、Adapter、Bean)导致 Activity 臃肿,这是典型的没有遵守单一职责造成的。

下面是违反单一职责原则的反例:

在这里插入图片描述
在这里插入图片描述

如果这样设计,随着需要实现的不同功能的类越来越多,这样的实现方式就会变成一种继承灾难。
在这里插入图片描述

  • 出现棱形继承,是抽象程度不够的表现。

单一职责原则的关键词:

  • 封装性
  • 职责划分
  • 细化抽象粒度

开闭原则(Open Closed Principle)

  • 对扩展开放,对修改关闭。

当软件需要变化时,尽量通过扩展的方式来实现变化,而不是通过修改已有代码。通常情况下继承是最简单的方式,因为这种方式能保证已经正常 work 的代码不动,但扩展的方式不仅仅是通过继承,更多的是通过持有抽象来拥抱不同的变化。例如 ImageLoader 可以通过持有一个 ImageCache 的接口类型变量,在使用时需要提供不同缓存策略时,set 方法注入 ImageCache 接口的不同实现,达到不修改已有类的目的。

下面是违反开闭原则的例子:

在这里插入图片描述

正确的做法:

在这里插入图片描述

  • 在面向对象语言里,提高代码可维护性的过程,大多数时候都是在消除条件分支语句(if & else )。

开闭原则的关键词:

  • 可扩展性
  • 抽象变化
  • 可维护性
  • 灵活性
  • 稳定性

里氏代换原则(Liskov Substitution Principle )

  • 任何基类出现的地方,子类也同样适用,是多态的体现。
  • 里氏代换,是开闭原则的一种实现方案,也是大部分设计模式的基础。
  • 只有满足里氏代换,子类能替换基类,才能够说明基类是真正能够被复用的。

比如 show(View) 方法传入不同的子类实现 TextView、 ImageView 等,就是使用 View 的不同子类来替换基类 View。再比如 Solider 类持有一把抽象的枪 Gun,使用时再传入具体的实现。因此一般持有抽象的类成员、方法参数都可以认为是里氏替换的例子。里氏替换的核心原理是抽象,且子类必须完全实现父类的方法,否则,应该用组合代替继承。

里氏替换的例子:
在这里插入图片描述
代理模式:
在这里插入图片描述

  • 这里代理者和被代理者都实现了同样的接口,定义代理者时使用基类来引用。只有这样基类才是可复用的。

里氏代换原则的关键词:

  • 可扩展性
  • 抽象
  • 可维护性
  • 复用基类
  • 开闭原则

依赖倒置原则(Dependence Inversion Principle)

  • 依赖抽象接口,而非具体实现。

依赖倒置原则一句话就是:面向接口编程,或面向抽象编程。因为类与类之间一旦依赖于细节,就会产生耦合,例如 ImageLoader 中的缓存策略依赖于某一种具体的实现 MemoryCache 而不是 ImageCache 接口,这样需要更换缓存策略时就会不停的修改 ImageLoader 类。

在这里插入图片描述
在这里插入图片描述

  • 比如,业务类中写了 18 层的继承关系,每一层都是实现类,还依赖了其他实现类,让人理不清关系。

依赖倒置原则的最大好处:降低耦合、隔绝变化

  • 不同业务之间,不被彼此的变化影响;
  • 明确开发、测试人员职责,提高协作效率;
  • 故障隔离,单独业务的故障问题,不应该影响全局。

依赖倒置原则的关键词:

  • 低耦合
  • 隔绝变化
  • 扩展性
  • 灵活性

文章来源:https://blog.csdn.net/lyabc123456/article/details/135311702
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。