聊一聊设计模式

102 阅读3分钟

最近看了一些关于设计模式的文章, 这里就来聊一下自己对于设计模式的一些看法.

首先说一下为什么需要设计模式. 软件本身是复杂的, 这是它的本质, 不会因为你使用何种开发模式而导致其复杂度降低. 而编程就是实现具体的业务场景, 无论你使用何种模式, 何种语言, 机器并不感知, 它只会按照生成的最终指令执行. 但是, 编程这个动作是人来执行的, 所以我们的最终目的是节省人理解成本, 开发成本和维护成本, 尽可能减少或压缩人的心力负担. 为了写出的代码更容易让人理解和维护, 总结出了一些原则, 基于这些原则给出了一些设计模式. 对于大型项目, 使用合理的设计模式可以让我的项目易于扩展和维护. 当然, 当我们想在项目中使用设计模式时也会促进我们对于业务的思考, 从而减少业务和实现之间的鸿沟.

下面谈一下设计模式的原则, 或者我们开发过程中应该尽可能满足或去思考的一些规范, 符合这些原则未必能写出让人更好维护的代码, 但是不满足这些原则的代码肯定很难维护:

  • 单一职责

一个类或者一个模块只应该有一个修改的原因. 简单来说, 就是一个类或者模块只做一件事或者一类事情.

  • 开闭原则

对扩展开放, 对修改关闭. 简单来说, 我们在设计一些功能或模块时, 可以思考下对于后续的功能是否能够通过扩展「新增类和模块」来完成, 而不是更新现有的复杂逻辑.

  • 里氏替换原则

任何基类可以出现的地方, 子类一定可以出现. 简单来说, 子类在继承父类的时候可以对功能进行补充, 但不能对方法进行重写「go 没有重写这个概念」, 重写之后会导致子类无法替换基类, 违背此原则。

  • 接口隔离原则

使用多个隔离的接口, 而不是使用一个大而全的接口, 尽可能减少依赖。

  • 依赖倒置原则

高层模块不应该依赖底层模块, 两者都应该依赖其抽象; 抽象不应该依赖细节, 而应该依赖抽象。核心思想就是面向接口编程, 通过定义接口可以让模块只关注模块自身的逻辑, 而不用关注依赖模块的实现细节。

  • 合成复用原则

尽量使用组合的方式, 而不是使用继承。简单来说, 我们应该尽可能的使用类的组合方式实现功能, 尽量减少使用继承「需要暴露父类的是实现细节」。

基于这些原则, 将设计模式分为三类:创建型「如何创建对象」、结构型「对象之间的组织结构」、行为型「对象之间的通信」, 每一类都有不同个模式来实现。

我们不能为了设计模式而去设计模式, 而是让设计模式给我们提供更多的思考。在软件开发中, 我们要明确我们的首要目标是实现业务需求, 在实现业务诉求的基础上, 尽可能让代码更容易阅读, 更容易维护, 本质上还是减少开发者的心智负担。那么, 我们在开发的时候就未必一定要推崇使用什么样的设计模式。通常是先思考, 实现的功能是什么, 具体实现的时候会拆分成哪些最小单元, 最小单元如何组织, 是否方便后续的扩展和迭代。