0%

设计模式入门

七大软件架构设计原则

开闭原则

开闭原则(Open-Closed Principle,OCP)指一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。

所谓开闭,也正是对扩展和修改两个行为的一个原则。强调的是用抽象构建框架,用实现扩展细节,可以提高软件系统的可复用性及可维护性。开闭原则是面向对象设计中最基础的设计原则。它指导我们如何建立稳定灵活的系统,例如版本更新,我们尽可能不修改源码,但是可以增加新功能。

依赖倒置原则

依赖倒置原则(Dependence Inversion Principle,DIP)指设计代码结构时,高层模块不应该依赖底层模块,二者都应该依赖其抽象。抽象不应该依赖细节,细节应该依赖抽象。通过依赖倒置,可以降低类与类之间的耦合性,提高系统的稳定性,提高代码的可读性和可维护性,并降低修改程序带来的风险。

单一职责原则

单一职责原则(Simple Responsibility Principle,SRP)指不要存在一个以上导致类变更的原因。

假设有一个Class负责两个职责,一旦发生需求变更,修改其中一个职责的逻辑代码,有可能会导致另一个职责的功能发生故障。这样一来,这个Class就存在两个导致类变更的原因。如何解决这个问题呢?我们就要分别用两个Class来实现两个职责,进行解耦。后期需求变更维护互不影响。这样的设计,可以降低类的复杂度,提高类的可读性,提高系统的可维护性,降低变更引起的风险。总体来说就是一个Class、Interface、Method只负责一项职责。

接口隔离原则

接口隔离原则(Interface Segregation Principle,ISP)指用多个专门的接口,而不使用单一的总接口,客户端不应该依赖它不需要的接口。

这个原则指导我们在设计接口时,应当注意以下几点。

  1. 一个类对另一个类的依赖应该建立在最小接口上。
  2. 建立单一接口,不要建立庞大臃肿的接口。
  3. 尽量细化接口,接口中的方法尽量少(不是越少越好,一定要适度)。

接口隔离原则符合“高聚合、低耦合”的设计思想,使得类具有很好的可读性、可扩展性和可维护性。在设计接口的时候,要多花时间思考,要考虑业务模型,包括还要对以后可能发生变更的地方做一些预判。所以,在实际开发中,我们对抽象、业务模型的理解是非常重要的。

迪米特法则

迪米特法则(Law of Demeter,LoD)又叫作最少知道原则(Least KnowledgePrinciple,LKP),指一个对象应该对其他对象保持最少的了解,尽量降低类与类之间的耦合。

里氏替换原则

里氏替换原则(Liskov Substitution Principle,LSP)指如果对每一个类型为T1的对象O1,都有类型为T2的对象O2,使得以T1定义的所有程序P在所有对象O1都替换成O2时,程序P的行为没有发生变化,那么类型T2是类型T1的子类型。

定义看上去比较抽象,我们重新解释一下,可以理解为一个软件实体如果适用于一个父类,则一定适用于其子类,所有引用父类的地方必须能透明地使用其子类的对象,子类对象能够替换父类对象,而程序逻辑不变。也可以理解为,子类可以扩展父类的功能,但不能改变父类原有的功能。

合成复用原则

合成复用原则(Composite/Aggregate Reuse Principle,CARP)指尽量使用对象组合(has-a)或对象聚合(contanis-a)的方式实现代码复用,而不是用继承关系达到代码复用的目的。

合成复用原则可以使系统更加灵活,降低类与类之间的耦合度,一个类的变化对其他类造成的影响相对较小。

继承,又被称为白箱复用,相当于把所有实现细节暴露给子类。组合/聚合又被称为黑箱复用,对类以外的对象是无法获取实现细节的。我们要根据具体的业务场景来做代码设计,其实也都需要遵循面向对象编程(Object OrientedProgramming,OOP)模型。

设计原则小结

其他补充设计原则

KISS原则(Keep It Simple and Stupid)

尽量保持简单。

KSS原则算是一个万金油类型的设计原则,可以应用在很多场景中。它不仅经常用来指导软件开发,还经常用来指导更加广泛的系统设计、产品设计等,比如,冰箱、建筑、 iPhone手机的设计等等。

我们知道,代码的可读性和可维护性是衡量代码质量非常重要的两个标准。而KSS原则就是保持代码可读和可维护的重要手段。代码足够简单,也就意味着很容易读慬,bug比较难隐。

如何写出满足KIsS原则的代码?

  • 不要使用同事可能不懂的技术来实现代码。还有一些编程语言中过于高级的语法等。
  • 不要重复造轮子,要善于使用已经有的工具类库。经验证明,自己去实现这些类库,出bug的概率会更高,维护的成本也比较高。
  • 不要过度优化。不要过度使用一些奇技淫巧(比如,位运算代替算术运算、复杂的条件语句代if-else、使用一些过于底层的函数等)来优化代码,牺牲代码的可读性。

YAGNI原则

YAGN原则的英文全称是: You ain’ t Gonna Need It。直译就是:你不会需要它。这条原则也算是万金油了。当用在软件开发中的时候,它的意思是:不要去设计当前用不到的功能;不要去编写当前用不到的代码。

实际上,这条原则的核心思想就是:不要做过度设计

比如,我们的系统暂时只用 Redis存储配置信息,以后可能会用到 ZooKeeper。根据YAGNI原则,在未用到 ZooKeeper之前,我们没必要提前编写这部分代码。当然,这并不是说我们就不需要考虑代码的扩展性。我们还是要预留好扩展点,等到需要的时候,再去实现ZooKeeper存储配置信息这部分代码。

DRY原则

DRY是 Don’t repeat yourself 的缩写,意思是”不要重复自己”。

软件工程名著《The Pragmatic Programmer》首先提出了这个原则。它的涵义是,系统的每一个功能都应该有唯一的实现。也就是说,如果多次遇到同样的问题,就应该抽象出一个共同的解决方法,不要重复开发同样的功能。

这个原则有时也称为”一次且仅一次”原则(Once and Only Once)。

UML

统一建模语言(Unified Modeling Language,UML)是一种为面向对象系统的产品进行说明、可视化和编制文档的标准语言,是非专利的第三代建模和规约语言。UML是一种面向对象设计的建模工具,是在开发阶段说明、可视化、构建和书写一个面向对象软件密集系统的制品的开放方法,但独立于任何具体的程序设计语言。

关于UML具体含义,用到去搜一下。比较重要的是类图时序图

UML类图主要包含以下方面

  • 成员
    • 可见范围 ( Visibility)
    • 范围(Scope,静态变量|成员变量)
  • 关系
    • 实例之间的关系
      • 依赖
      • 关联
      • 聚合
      • 组合
    • 类之间的关系
      • 实现
      • 继承
    • 一般关系
    • 多重性

参考维基百科 https://en.wikipedia.org/wiki/Class_diagram#Generalization/Inheritance

常用UML工具推荐

  1. draw.io(开源软件,可以直接下载,也有web端)
  2. plantuml https://plantuml.com/zh/ 可以用写代码的方式画uml