设计模式上篇之设计原则与思想

5/21/2023 partern

# 面向对象

# 四大特性

1. 抽象

2. 封装

3. 继承

4. 多态:同一操作作用于不同对象会产生不同的效果,一般是通过继承来实现 9

# 接口 VS 抽象类

  1. 接口

    1. 只有方法,没有成员变量
    2. 方法没有实现,也称为抽象方法
    3. 类实现接口时必须实现接口中的所有方法(抽象方法)
    4. 类可以实现多个接口(很像多继承)
  2. 抽象类

    1. 可以有方法,也可以有成员变量
    2. 方法可以有实现,也可以没有实现
    3. 抽象类不能被实例化,只能被继承
    4. 子类继承抽象类必须实现抽象类中的所有抽象方法(未实现的方法)

# 设计思想

1. 基于接口而非实现编程

2. 多用组合少用继承

# 贫血模型 VS 充血模型

  1. 贫血模型

    1. 类中只有数据没有方法,是典型的面向过程编程方式
  2. 充血模型

    1. 类中即有数据也有方法,是典型的面向对象编程方式

# 面向对象开发主要流程

1. 面向对象分析(OOA Object Oriented Analysis):产出详细的需求描述

2. 面向对象设计(OOD Object Oriented Design):根据需求描述产出类

3. 面向对象编程(OOP Object Oriented Programming):基于对象编码实现

# 设计原则

剑圣独孤求败的绝招是什么,没有招,无招胜有招 就算不知道设计模式,如果理解了设计原则,也能写出 高内聚、低耦合 的好代码 设计模式只是前人把优化过程中常见的问题和解决方法加以总结,方便后人参考而已 在项目的实际开发过程中不要过于教条主义,要根据实际的应用场景进行设计原则的选择,甚至创造出独属于那个应用场景的新的设计原则

# SOLID 原则

  1. 单一职责原则 (SRP Single Responsibility Principle)
    1. 一个类或者模块只负责完成一个职责(或者功能)
  2. 开闭原则(OCP Open Closed Principle)
    1. 对扩展开放(提高代码的可扩展性)
    2. 对修改关闭(提高代码的稳定性)
  3. 里氏替换原则(LSP Liskov Substitution Principle)
    1. 子类完美继承父类
    2. 子类的实现不能替换原有父类的逻辑,但可以对功能做扩展(有点类似于开闭原则呀)
  4. 接口隔离原则(ISP Interface Segregation Principle)
    1. 接口的调用者不应该被强迫依赖它不需要的接口
    2. 对接口的理解
      1. 一组 API 接口集合
      2. 单个接口或函数
      3. OOP 中的接口
  5. 依赖反转原则(DIP Dependency Inversion Principle)
    1. 控制反转(IOC Inversion Of Control)
    2. 依赖注入(DI Dependency Injection)
      1. 算是解耦的一种方式
      2. 提高了代码的可扩展性
    3. 依赖反转原则也叫依赖倒置原则
      1. 高层模块不依赖底层模块,它们共同依赖同一个抽象
      2. 抽象不依赖具体实现细节,具体实现细节依赖抽象

# LOD 原则

Law Of Demeter

也叫最小知识原则,强调的是类之间的依赖,也就是要 松耦合,符合高内聚、低耦合的设计思想

  1. 不该有直接依赖关系的类之间,不要有依赖
  2. 有依赖关系的类之间,尽量只依赖必要的接口

# KISS 原则

Keep It Simple and Stupid

保持尽量简单

# YAGNI 原则

You Ain't Gonna Need It

不要过度设计,不需要的不要做

# DRY 原则

Don't Repeat Yourself

不要写重复的代码

这里的重复体现在:

  1. 实现逻辑重复
  2. 功能语义重复
  3. 代码执行重复

实现逻辑重复,但功能语义不重复的代码,并不违反 DRY 原则

实现逻辑不重复,但功能语义重复的代码,也算是违反 DRY 原则

代码执行重复也算是违反 DRY 原则

# 代码重构

# 四要素

  1. 目的:为什么要重构?
    1. 提高代码的 可读性、可维护性
  2. 对象:对什么进行重构?
    1. 大重构:针对 系统、模块、代码结构、类之间关系 等,使用解耦等技巧
    2. 小重构:针对 类,函数 等,使用编程规范等技巧即可
  3. 时机:何时进行重构?
    1. 持续重构
    2. 开发阶段、维护阶段等各个阶段都需要进行重构
  4. 方法:如何进行重构?
    1. 编写单元测试
    2. 编写可测试性代码
    3. 使用解耦方法(实现高内聚、松耦合)
      1. 封装与抽象
      2. 中间层
      3. 模块化
      4. 其它设计原则与思想

# 编程规范

# 命名

  1. 命名的关键是能准确达意。对于不同作用域的命名,我们可以适当地选择不同的长度。

  2. 我们可以借助类的信息来简化属性、函数的命名,利用函数的信息来简化函数参数的命名。

  3. 命名要可读、可搜索。不要使用生僻的、不好读的英文单词来命名。命名要符合项目的统一规范,也不要用些反直觉的命名。

  4. 接口有两种命名方式:一种是在接口中带前缀“I”;另一种是在接口的实现类中带后缀“Impl”。对于抽象类的命名,也有两种方式,一种是带上前缀“Abstract”,一种是不带前缀。这两种命名方式都可以,关键是要在项目中统一。

# 注释

  1. 注释的内容主要包含这样三个方面:做什么(What)、为什么(Why)、怎么做(How)。对于一些复杂的类和接口,我们可能还需要写明“如何用”。

  2. 类和函数一定要写注释,而且要写得尽可能全面详细。函数内部的注释要相对少一些,一般都是靠好的命名、提炼函数、解释性变量、总结性注释来提高代码可读性。

# 代码风格

  1. 函数、类多大才合适?函数的代码行数不要超过一屏幕的大小,比如 50 行。类的大小限制比较难确定。

  2. 一行代码多长最合适?最好不要超过 IDE 的显示宽度。当然,也不能太小,否则会导致很多稍微长点的语句被折成两行,也会影响到代码的整洁,不利于阅读。

  3. 善用空行分割单元块。对于比较长的函数,为了让逻辑更加清晰,可以使用空行来分割各个代码块。

  4. 四格缩进还是两格缩进?我个人比较推荐使用两格缩进,这样可以节省空间,尤其是在代码嵌套层次比较深的情况下。不管是用两格缩进还是四格缩进,一定不要用 tab 键缩进。

  5. 大括号是否要另起一行?将大括号放到跟上一条语句同一行,可以节省代码行数。但是将大括号另起新的一行的方式,左右括号可以垂直对齐,哪些代码属于哪一个代码块,更加一目了然。

  6. 类中成员怎么排列?在 Google Java 编程规范中,依赖类按照字母序从小到大排列。类中先写成员变量后写函数。成员变量之间或函数之间,先写静态成员变量或函数,后写普通变量或函数,并且按照作用域大小依次排列。

# 编码技巧

  1. 将复杂的逻辑提炼拆分成函数和类。

  2. 通过拆分成多个函数或将参数封装为对象的方式,来处理参数过多的情况。

  3. 函数中不要使用参数来做代码执行逻辑的控制。

  4. 函数设计要职责单一。

  5. 移除过深的嵌套层次,方法包括:去掉多余的 if 或 else 语句,使用 continue、break、return 关键字提前退出嵌套,调整执行顺序来减少嵌套,将部分嵌套逻辑抽象成函数。

  6. 用字面常量取代魔法数。

  7. 用解释性变量来解释复杂表达式,以此提高代码可读性。

Last Updated: 5/25/2023, 9:14:50 PM