摘要生成中...
AI 摘要
Hunyuan-lite
这是一篇索引文章

编程范式与编程风格

常见的编程范式/编程风格:

不同的编程范式之间并不是截然不同的,总是有一些相同的编程规则。比如,不管是面向过程、面向对象还是函数式编程,它们都有变量、函数的概念,最顶层都要有 main 函数执行入口,来组装编程单元(类、函数等)。只不过,面向对象的编程单元是类或对象,面向过程的编程单元是函数,函数式编程的编程单元是无状态函数。

设计原则

站内文章设计原则 文章中介绍 SOLID 等代码编写和设计原则。

设计模式

设计模式是指针对软件开发过程中重复发生的问题的解决方法。其中以被称为 Gang of Four 整理出的 23 种设计模式最为有名。除此以外还有其他设计模式,参考:

关于「对象」

GoF 设计模式中的「对象」,是指系统中承担特定职责的最小功能单元。它不是现实世界的「物体」,而是程序中负责完成某项具体任务的实体(即类实例)。对象封装了数据(状态)和操作(行为),并将两者紧密绑定。

在设计模式的语境中,对象的意义不在于其作为「类实例」本身,而在于其所扮演的角色及其在协作中的交互方式。不同的设计模式其实就是组织这些对象并协调其协作关系的不同方法。可以用一句形象的话来形容:对象是程序中的「小工人」,每个设计模式都在教这些工人如何分工、如何协同、如何履职。

「模式病」

设计模式不是万能的,我们需要明确知道自己的软件中存在什么样的问题,明确设计模式可以解决什么问题,才能选出合适的设计模式。设计模式重要性在于快速掌握经验丰富的开发人员才具有的知识和经验,但也没必要机械地背下来。不要为了「设计模式而设计模式」。

鲁布·戈德堡机械

「鲁布·戈德堡机械」(Rube Goldberg Machine)源自美国漫画家鲁布·戈德堡的讽刺作品。他画了一系列荒诞的机器,这些机器通过大量不必要的中间步骤去完成一个极其简单的目标。它后来成为工程领域的一个典型隐喻:过度复杂、设计过头、为了设计而设计的系统。例如,为了按一下电灯开关,设计一个球滚下斜坡,撞倒一个摆锤,点燃一堆烟火,拉动一根绳子,最终才让开关「啪」一下亮灯——简单的事,被极端复杂化。

GoF 23 经典的设计模式

如果把软件工程看作人类理性的延伸,那么它的历史其实是一部复杂性管理史。20 世纪 90 年代,软件正经历一场危机:

  • 面向对象编程从学术界的「玩具」变成了工业界的主流;
  • C++ 正在征服世界,Smalltalk 的优雅令人着迷,而 Java 即将诞生;
  • 代码不断膨胀。

GoF(四人,Gang of Four)注意到软件与建筑之间的相似性:二者都是在约束中进行创造,都需要平衡功能与美感,也都面临着复杂性的挑战。于是,他们开始收集、整理并提炼那些在优秀软件中反复出现的「形式」。最终,23 个设计模式被精心挑选出来,并划分为三大类型,树立了软件设计模式领域的里程碑 [1]

image.png

GoF 所提出的设计模式主要是基于以下面向对象设计原则:

  • 对接口编程而不是对实现编程。
  • 优先使用对象组合而不是继承。

因此,书中提到的 23 中设计模式,也称为经典的「GoF 设计模式」。

GoF 的伟大之处在于:他们首次将「经验」转化为「词汇」。——《Agent 设计模式》黄佳

有了 GoF 对各种常见模式的定义,不同开发者之间的沟通壁垒降低了。

模式分类

类型 创建型 结构型 行为型
解决问题 解决构建复杂、耦合和可拓展性的问题 解决系统模块之间的连接方式与复杂度问题。 解决职责划分、耦合度和可扩展的业务流程问题。
本科时期我的简记

  • 创建型:建造单例原型工厂
  • 结构型:ABCompositeDFP(不包含创建型),250830 或「想焖主包」(享门组包 Wrapper)。
  • 行为型:剩下的都是行为型。

创建型:解决对象创建的问题

创建型模式 创建类的特点
单例模式 创建全局唯一的对象
工厂方法模式 创建不同但是相关类型的对象(继承同一父类或者接口的一组子类),由给定的参数来决定创建哪种类型的对象。
建造者模式 创建复杂对象,可以通过设置不同的可选参数,「定制化」地创建不同的对象
原型模式 创建成本比较大的对象,利用对已有对象进行复制的方式进行创建,以达到节省创建时间的目的。
抽象工厂 生产「产品族」,保持同一系列产品间的一致性与兼容性。

结构型:一些类或对象组合在一起的经典结构

结构型模式 核心目的
适配器 让原本接口不兼容的两个组件可以一起工作。
桥接 分离「抽象部分」和「实现部分」,让两边可以独立扩展。
组合 以「树形结构」统一处理单个对象与组合对象。
装饰器 在不修改原始类的前提下动态地给对象添加功能。
外观(门面) 对复杂子系统提供一个「统一、简单」的入口。
享元 通过「共享」细粒度对象,减少内存消耗。
代理 控制对某个对象的访问,在访问前后附加额外逻辑。

行为型:类和对象之间的交互

行为型模式 核心目的
责任链 把请求沿着一条链传递下去,每个节点决定「处理」或「继续传递」。
命令 把「请求」封装成对象,便于排队、撤销、重做、日志记录。
迭代器 提供统一方式,按顺序访问聚合对象内部元素,而不暴露其内部结构。
观察者 建立「一对多」的通信机制,状态变化时自动通知所有订阅者。
策略 将可替换的算法封装起来,运行时按需切换。
模板方法 在父类中定义「处理流程骨架」,子类只重写其中的某些步骤。
访问者 在不改变数据结构的前提下,为其增加新操作。
状态 允许对象在其内部状态发生改变时改变自身行为。
备忘录 在不破坏封装的前提下,捕获并恢复对象的内部状态。
中介者 通过一个中介对象封装一系列对象之间的交互。
解释器 给定一种语言,定义其文法表示,并实现一个解释器来解析和处理该语言。

设计模式之间的区别

23 种设计模式可进一步划分为创建型、组合型和行为型设计模式。

每个设计模式都应该由两部分组成:第一部分是应用场景,即这个模式可以解决哪类问题;第二部分是解决方案,即这个模式的设计思路和具体的代码实现。如果只观察设计模式的代码实现,你会发现一些模式是十分相似的:

但设计模式之间的主要区别还是在于设计意图,即应用场景。对于某些模式之前的相似性比较,相关设计模式文章中会有所涉及。

「用类/示例来表示 XXX」的模式

《图解设计模式》结城浩

在面向对象编程中,是用类表示对象的。也就是说,程序的设计者需要考虑用类来表示什么东西。类对应的东西可能存在于真实世界中,也可能不存在于真实世界中。对于后者,可能有人看到代码后会感到吃惊:这些东西居然也可以是类啊。

「用类/示例来表示 XXX」的模式均为行为型设计模式:

多线程的设计模式

上面 GoF 23 个经典设计模式中部分模式也有多线程的实现,如:

此外,一些和多线程有关的设计模式有:

书籍索引

下面是我阅读过的相关书籍:

其他推荐经典:

  • 《Design Patterns: Elements of Reusable Object-Oriented Software》GoF
  • 《重构:改善既有代码的设计》马丁·福勒
  • 《敏捷软件开发:原则、模式与实践》罗伯特·马丁
  • 《领域驱动设计:软件核心复杂性应对之道》埃里克·埃文斯

本文参考

其他资源:Laws of Software Engineering


  1. 上世纪 90 年代,由 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides 四人合作出版了《Design Patterns: Elements of Reusable Object-Oriented Software》一书,中文译名为《设计模式 - 可复用的面向对象软件元素》。该书首次提到了软件开发中设计模式的概念,并收录了 23 种设计模式。 ↩︎