design_patterns/notes.md
Yuki f7eac92f68
feat: Singleton.
Implemented a demo for the Singleton.
2025-04-05 22:58:40 +08:00

36 lines
3.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 设计模式笔记
## 简单工厂Simple Factory
简单工厂将对象的创建过程与使用过程解耦,客户端只需传入参数,而不需要关心创建的细节和具体的子类类型。这样,当需要添加新的产品子类时,只需在工厂中扩展创建逻辑,无需修改客户端代码,从而实现了对变化的封装,提升了系统的可扩展性与可维护性。
## 工厂模式Factory Method
简单工厂里,我们的输入参数是一样的,如何处理建造时参数不同的情况呢?例如 `Circle` 接受圆心和半径,而 `Square` 接受两个对角的点。
工厂模式给出了解决方案。对于每个新的子类,有一个专门的工厂类生成这个新的子类,进而工厂类可以使用不同的参数构建新的子类。
工厂模式相对简单工厂,通过解耦获取工厂和生成子类实例,获取了更大的灵活性。比如客户端可以在得到工厂后,进一步根据工厂类型向用户请求输入。但是对于一个新类就需要额外需要一个工厂,稍微麻烦些。通过同时使用两种方式,可以达到最大的灵活性。
## 抽象工厂Abstract Factory
抽象工厂进一步的将工厂本身也作为一种产品。它定义了一个“工厂族”的接口,规定了工厂需要生产哪些种类的产品。客户端从抽象工厂获取一个具体的工厂,再从这个工厂中制造一组相互关联的具体产品。
这可以用于创建一系列相关或相互依赖的对象,而不指定它们的具体类。也就是说,它解决了产品族一致性的问题。这在组件风格切换、平台适配、多模块协作等方面很有用。
## 生成器模式Builder
假定有一种复杂对象(比如电脑,需要有 CPU内存主板等如何构建这种复杂对象呢朴素的做法是有一个接受很多参数的构造函数这显然不好因为参数不总是都用上的。另一种做法是扩展电脑基类但是这意味着给电脑增加新的外设会很复杂因为需要添加子类。
解决方案是有一种生成器类专门负责构建复杂对象。对于每一种参数,生成器类定义了接受各个参数的函数,从而做到分步创建对象。参数输入结束后,生成器类可以基于之前输入的参数创建这一复杂对象。
对于复杂场景,比如生成器需要输入十种参数,可以添加一个指导者封装这些输入这几种参数的过程。它提供了一种简化的构建流程,客户端不需要关心构建细节,代价是牺牲了一定的灵活性,因为客户无法定制每一步。
## 单例模式Singleton
有些时候,我们希望一个类只被实例化一次,且能在全局被访问,比如一个事件模拟器。朴素的想法是直接用一个全局变量。但这使得模块间强耦合,这些模块依赖隐式的、看不见的全局状态。且多个全局变量出现时依赖难以管理。
单例模式是一种解决方案,这个类只通过静态的 `get_instance()` 提供统一访问方式,并且不提供拷贝构造和赋值操作。这样多个依赖的全局变量可以在这个类里管理。此外测试时可以只改内部实现,对外接口不变,提高了可维护性与可测试性。
具体实现上有一些技巧。为了只创建一次,可以用 `get_instance()` 中使用 `static` 变量(懒汉式),也可以这个类有一个 `static` 类成员(饿汉式),还可以用 `static` 指针成员,对于指针为空时(第一次访问)额外做初始化(需要注意创建时的线程安全,比如双检查)。