最近看了一些关于设计模式的文章, 这里就来聊一下自己对于设计模式的一些看法.
首先说一下为什么需要设计模式. 软件本身是复杂的, 这是它的本质, 不会因为你使用何种开发模式而导致其复杂度降低. 而编程就是实现具体的业务场景, 无论你使用何种模式, 何种语言, 机器并不感知, 它只会按照生成的最终指令执行. 但是, 编程这个动作是人来执行的, 所以我们的最终目的是节省人理解成本, 开发成本和维护成本, 尽可能减少或压缩人的心力负担. 为了写出的代码更容易让人理解和维护, 总结出了一些原则, 基于这些原则给出了一些设计模式. 对于大型项目, 使用合理的设计模式可以让我的项目易于扩展和维护. 当然, 当我们想在项目中使用设计模式时也会促进我们对于业务的思考, 从而减少业务和实现之间的鸿沟.
下面谈一下设计模式的原则, 或者我们开发过程中应该尽可能满足或去思考的一些规范, 符合这些原则未必能写出让人更好维护的代码, 但是不满足这些原则的代码肯定很难维护:
- 单一职责
一个类或者一个模块只应该有一个修改的原因. 简单来说, 就是一个类或者模块只做一件事或者一类事情.
- 开闭原则
对扩展开放, 对修改关闭. 简单来说, 我们在设计一些功能或模块时, 可以思考下对于后续的功能是否能够通过扩展「新增类和模块」来完成, 而不是更新现有的复杂逻辑.
- 里氏替换原则
任何基类可以出现的地方, 子类一定可以出现. 简单来说, 子类在继承父类的时候可以对功能进行补充, 但不能对方法进行重写「go 没有重写这个概念」, 重写之后会导致子类无法替换基类, 违背此原则。
- 接口隔离原则
使用多个隔离的接口, 而不是使用一个大而全的接口, 尽可能减少依赖。
- 依赖倒置原则
高层模块不应该依赖底层模块, 两者都应该依赖其抽象; 抽象不应该依赖细节, 而应该依赖抽象。核心思想就是面向接口编程, 通过定义接口可以让模块只关注模块自身的逻辑, 而不用关注依赖模块的实现细节。
- 合成复用原则
尽量使用组合的方式, 而不是使用继承。简单来说, 我们应该尽可能的使用类的组合方式实现功能, 尽量减少使用继承「需要暴露父类的是实现细节」。
基于这些原则, 将设计模式分为三类:创建型「如何创建对象」、结构型「对象之间的组织结构」、行为型「对象之间的通信」, 每一类都有不同个模式来实现。
我们不能为了设计模式而去设计模式, 而是让设计模式给我们提供更多的思考。在软件开发中, 我们要明确我们的首要目标是实现业务需求, 在实现业务诉求的基础上, 尽可能让代码更容易阅读, 更容易维护, 本质上还是减少开发者的心智负担。那么, 我们在开发的时候就未必一定要推崇使用什么样的设计模式。通常是先思考, 实现的功能是什么, 具体实现的时候会拆分成哪些最小单元, 最小单元如何组织, 是否方便后续的扩展和迭代。