Golang设计模式(一):设计原则&设计模式介绍


目录:

设计原则&设计模式介绍

学习设计模式的关键点:

  • 设计原则,以及设计模式的使用场景和优缺点,实现相对来说还没有那么重要
  • 如果是常见的设计模式是武术招式,那么设计原则就是内功心法,没有内功心法那么招式套路也就是花架子
  • 熟练掌握不同设计模式的使用场景可以帮助我们学会见招拆招,灵活应用而不是只会套路

设计原则

所有设计模式的核心都是设计原则,可以说所有的设计模式都是在设计原则的基础上针对某些特定的场景进行抽象化。因此学习设计模式就是学习设计原则以及其对应的应用

设计原则和思想其实比设计模式更加普适和重要,掌握了代码的设计原则和思想,我们甚至可以自己创造出来新的设计模式

SOLID原则

常见的设计原则有五大原则,使用SOLID进行表示,分别是:

  • S:单一职责原则
  • O:开放封闭原则
  • L:里氏替换原则
  • I:接口隔离原则
  • D:依赖倒置原则

单一职责原则

单一职责原则(Single Responsibility Principle):对类来说,即一个类应该只负责一项职责。

如类A负责两个职责:职责1,职责2。当职责1执行的过程中可能会影响到职责2的功能。此时需要将类A拆分为两个类。

单一职责原则的优点:

  • 降低类的复杂度,一个类只负责一项职责。
  • 提高类的可读性,可维护性
  • 降低类变更所引起的风险

通常情况下,我们应该遵守单一职责原则。单一职责原则可以分为类级别以及方法级别。

只有在类逻辑足够简单,才可以在代码级违反单一职责原则;只有在类中方法数量足够少,才可以在方法级别保持单一原则。

常见的不满足单一职责原则的情况(出现这种情况就需要进行拆分了):

  • 类中的代码行数过多,函数或则属性过多
  • 类依赖的其他类过多
  • 类中私有方法过多
  • 比较难给类起一个名字
  • 类中大量集中的方法都是集中操作类中的某几个属性

开放封闭原则

开放封闭原则(Open Closed Principle): 对一个软件实体来说,比如类,模块和函数应该对扩展开放,对修改关闭。即用抽象构建框架,用实现扩展细节。

这是编程中最基础、最重要的设计原则,也就是说,当软件需要变化的时候,尽量通过扩展软件实体(新增方法、函数、属性或类)的行为来实现变化,而不是通过修改已有代码来实现变化。

使用设计模式的目的就是为了遵循开放封闭原则。

常见做法:

  • 多态
  • 依赖注入
  • 基于接口而非实现
  • 装饰、策略、模版、职责链等大部分设计模式

里氏替换原则

里氏替换原则(Liskov Substitution Principle):如果对每个类型为T1的对象o1,都有类型为T2的对象o2,使得以T1定义的所有程序P在所有的对象o1都替换为o2时,程序P的行为没有发生变化,那么类型T2是类型T1的子类型。换句话说:所有引用基类的地方必须能够透明的使用其子类的对象,即子类对象能够替换程序中父类出现的任何地方,并且保证原来程序的逻辑行为不变及正确性不被破坏。

在使用继承的时候必须遵循里氏替换原则,也就是在子类中尽量不要重写父类的方法

里氏替换原则告诉我们,继承实际上让两个类的耦合性增强了。那么在适当的情况下,可以通过聚合、组合、依赖来解决问题。

接口隔离原则

接口隔离原则(Interface Segregation Principle):客户端不应该依赖它不需要的接口,即一个类对另一个类的依赖应该建立在最小的接口上。

依赖倒置原则

依赖倒置原则(Dependence Inversion Principle):

  • 高层模块不应该依赖底层模块,二者都应该依赖其抽象
  • 抽象不应该依赖细节,细节应该依赖抽象
  • 依赖倒置的中心思想是面向接口编程
  • 依赖倒置原则的设计理念:相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建的架构比以细节为基础搭建的架构要稳定的多。在Java中,抽象指的是接口或者抽象类,细节就是具体的实现类。
  • 使用接口或者抽象类的目的就是制定好规范,而不涉及任何具体的操作,把展现细节的任务交由他们的实现类去完成。

依赖倒置原则就是通常所说的控制反转:即在使用框架之后,整个程序的执行流程通过框架进行控制。流程的控制权由程序员反转给了框架。

依赖关系传递(依赖注入)的三种方式:

  • 接口传递
  • 构造器传递
  • setter方法传递

Go 中的依赖注入框架有:

依赖倒置原则的注意事项:

  • 底层模块尽量都要有抽象类和接口,或者两者都有,程序稳定性更好。
  • 变量的声明类型尽量都是抽象类和接口,这样我们的变量引用和实际对象间,就存在一个缓冲层,利于程序扩展和优化。
  • 继承时遵循里氏替换原则。

KISS原则

在程序的逻辑复杂度、实现难度、代码可读性方面进行保持简单。

常见原则:

  • 不要使用同事可能不懂的技术来实现代码
  • 不要重复造轮子,善于使用已经有的工具类库
  • 不要过度优化

YAGNI原则

不要对代码做过度的设计

DRY原则

不要重复的写代码(实现逻辑重复、功能语义重复、代码执行重复)。

在代码设计阶段需要考虑复用性,如果当下没有需求,并且未来也感觉没有,那么不要强求,有需求的时候在进行重构。

LOD原则

  • 高内聚:相近的功能应该放到同一个类中,不相近的功能不要放在同一个类中。
  • 低耦合:类与类之间的依赖关系简单清晰。即使两个类之间有依赖关系,一个类的代码改动也不能或者很少导致依赖类的代码改动。
  • 迪米特原则:不该有直接依赖关系的类之间不要有依赖,有依赖关系的类之间,尽量只依赖必要的接口。

设计模式

类型 设计模式 使用频率
创建型 单例模式(Singleton Design Pattern) 常用
创建型 工厂模式(Factory Design Pattern) 常用
创建型 建造者模式(Builder Design Pattern) 常用
创建型 原型模式(Prototype Design Pattern) 不常用
结构型 代理模式(Proxy Design Pattern) 常用
结构型 桥接模式(Bridge Design Pattern) 常用
结构型 装饰器模式(Decorator Design Pattern) 常用
结构型 适配器模式(Bridge Design Pattern) 常用
结构型 门面模式(Facade Design Pattern) 不常用
结构型 组合模式(Composite Design Pattern) 不常用
结构型 享元模式(Flyweight Design Pattern) 不常用
行为型 观察者模式(Observer Design Pattern) 常用
行为型 模版模式(Template Design Pattern) 常用
行为型 策略模式(Strategy Design Pattern) 常用
行为型 职责链模式(Chain Of Responsibility Design Pattern) 常用
行为型 状态模式(State Design Pattern) 常用
行为型 迭代器模式(Iterator Design Pattern) 常用
行为型 访问者模式(Visitor Design Pattern) 不常用
行为型 备忘录模式(Memento Design Pattern) 不常用
行为型 命令模式(Command Design Pattern) 不常用
行为型 解释器模式(Interpreter Design Pattern) 不常用
行为型 中介模式(Mediator Design Pattern) 不常用

后续文章将主要介绍一些常用的设计模式在 Golang 语言中的实现。