我想,基本的技术功底已有认识设计模式的必要与能力,但
如今的我,不过是看到了cpp实现他们的方式,但对于问题模式的识别,这重中之重,则还需锤炼许多。
凭我的经验还不足以对这些设计模式都有深刻的了解,暂时我对这些模式没有那么多归纳的东西。
大概是要等到遇到某个问题,用了某个方法的时候,偶然才会有体会吧。
So i would call it, upcoming deja vu ~~
这是wiki与GOF读后感与笔记,很简短。
1. Creational Design Patterns
The creational patterns aim to separate a system from how its objects are created, composed, and represented. They increase the system’s flexibility in terms of the what, who, how, and when of object creation. Creational pattern - Wikipedia
1.1 Simple Factory
创建对象的代码的复用
何时使用: 仅仅是代码复用
1.2 Factory Method
创建对象的接口
助记名: Object Creation Interface
何时使用: 延迟创建的实现,需要提供抽象的接口时
1.3 Abstract Factory
gathering up relevant Factory Method
into one packet
助记名:
Packet of Object Creation Interface
何时使用:需要创建的多种对象之间有相关关系, 面向某一种更高层概念的Factory(例如对于创建 床+窗+天花板, 可以有面向更高层概念的抽象工厂: 创建暖色调、冷色调、保暖etc 的一组对象)
1.4 Builder
提供比其他的构造模式更加细致的创建过程的控制,本质还是代码复用
Simple Factory
提供了代码复用的方式,但是纯传参控制的创建函数,在面对复杂的对象创建场景时会很麻烦(不然就只能提供超复杂的参数列表)
提供更细致的接口,可以提高创建过程的灵活性
从 Simple Factoy
到 Builder
,只是我们提供了更具弹性的创建过程的控制方式
助记名: Detailed Controller of Object Creation
何时使用: 需要对对象创建过程提供更细节的控制
1.5 Prototype
通过复制原型的方式创建对象
助记名: Copy Constructor
何时使用: 对象初始化状态都是一样的, 省却可能的复杂的创建过程
1.6 Singleton
顾名思义,唯一的对象即为单例
这更多的是表明对象数量限制,其他的诸如创建过程当然随意,静态初始化也好,访问时初始化也好
何时使用: 当你认为该类型对象全局只该存在一个的时候
2. Structural Design Patterns
2.1 Adapter
将旧接口适配到新接口
参考别名: Wrapper
助记名: Interface Wrapper
2.2 Bridge @todo fix
Bridge
指连接两层抽象的节点(第二层抽象接口的指针,UML 中的Abstraction::this.impl
). 当第二层抽象只有确定的实现的时候,Bridge
即为 Pimpl
UML description:
1 | Abstraction (abstract class) |
助记名: Two Layers Abstraction
or Decoupled Abstraction & Implementation
何时使用:
Pimpl: 隐藏实现细节
两层抽象,第二层与第一层的接口相互独立
2.3 Composite
将 一组对象视为单个对象一样操作
何时使用: 当前操作如果可以忽略操作的对象是单个对象还是一组对象的话,可以抽象出一致性的接口来
助记名: Treat Ones as one
何时使用:当前操作逻辑忽略操作对象是个独立对象还是一组对象
2.4 Decorator @todo fix
在同样的接口上提供额外的功能
尽管我们可以在这种模式下操作更多,比如直接跳过源对象的行为,但这不是一种好的设计。这种模式对于实现单一职责
很有帮助(运行时线性职责组合避免静态功能组合的爆炸)
助记名: Single Responsiblity Helper
:smirk:
何时使用: 太过复杂 [wiki](Decorator pattern - Wikipedia)
2.5 Facade
复杂子系统的简单接口
助记名: 表面
2.6 Flyweight
可共享的不可变对象
1 | Anything that will be cached is flyweight. |
助记名: Shareable Invariant
何时使用:在某类对象的某些属性可以共享的情况下,可以剥离出来,减少内存占用
2.7 Proxy
添加对原始对象的控制逻辑,在原始的对象使用过程中插入自定义逻辑
实现方式多和 Adapter
类似,只是目的不同
3. Behavioral Design Patterns
3.1 Chain-of-responsibility
Coupling the sender of a request to its receiver should be avoided.
It should be possible that more than one receiver can handle a request.
3.2 Command
解耦请求的触发与请求的执行,所谓 avoid hard-wired requests
上层只需关注请求的触发,所谓 Invoke a Command
, 而无需关注请求的执行
通过场景来理解:
- GUI button 相关的Action执行。Action就是一个Command对象,UI触发Action Command的执行
- 宏录制(Macro recording). 如果所有用户行为都被表示为 Command,则所谓录制用户一系列行为就是记录一系列的Command对象
- 多级回退(Multi-level undo). 比2更进一步的,Command对象如果有undo方法,那么多级回退就是Command对象的undo调用与出栈
当解耦请求的执行后,仅仅关注简单的请求触发(Invoke command),那么可以玩的很花,不是吗
3.3 Interpreter
wiki介绍解释器全文用的是针对语言解析的例子。设计模式解释动机时,描述的较为理想:如果一个特定类型的问题发生的频率足够高,那么就值得将该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解决这些句子来解决该问题。
核心就是找到问题域的可重入模式,构建层级的AST,简化问题的解决
3.4 Iterator
抽象容器访问接口,隐藏内部元素组织,解耦算法与容器。
想想 std::sort 用于vector<int> 与 int[] 这种随机访问容器时的迭代器即可知
3.5 Mediator
mediator对象负责处理多个对象间的复杂交互
- Air Traffic Control: In a simulation or software for air traffic control, a mediator might manage the communication between different aircraft, ground control, and other relevant systems. It ensures that messages are properly routed and that conflicts are resolved.
- Online Chat Systems: In a chat application, a mediator could manage the communication between different users in a chat room. It ensures that messages are delivered to the correct recipients and handles actions like joining or leaving the chat.
- Multiplayer Games: In a multiplayer game, a mediator might coordinate communication between different players, game objects, and the server. It ensures that actions performed by one player are properly communicated to others and that the game state remains synchronized.
3.6 Memento
Memento 记录对象的内部状态,于是对象可以回到之前的状态
是一种特殊的接口,让对象支持状态备份与恢复
Command undo 也可以实现状态恢复,不过Memento显然更加直截了当
应用领域:
- Text editors and IDEs: Implementing undo/redo functionality.
- Games: Managing game states and allowing players to revert to previous states.
- Transaction management: Handling rollback mechanisms in databases or distributed systems.
- User interfaces: Saving and restoring the state of complex UI components.
- Configuration management: Storing and restoring the configuration of an application.
3.7 Observer
- A one-to-many dependency between objects should be defined without making the objects tightly coupled.
- When one object changes state, an open-ended number of dependent objects should be updated automatically.
- An object can notify multiple other objects.
例子:
- Stock Market: In a financial application monitoring stock prices, various components might observe changes in the prices of specific stocks. When a stock price changes, the observers (e.g., components displaying the prices) are notified and update accordingly.
- Weather Monitoring System: In a weather monitoring system, different components might observe changes in temperature, humidity, pressure, etc. When any of these parameters change, the observers are notified, and relevant actions can be taken (e.g., displaying an alert).
- UI Components in MVC: In the Model-View-Controller (MVC) architectural pattern, views observe changes in the model and update themselves accordingly. For example, in a web application, a view might observe changes in the underlying data model and update the displayed content.
- Distributed Systems Communication: In a distributed system where different components need to be notified of changes or events, the Observer pattern can be used to facilitate communication. For example, in a publish-subscribe messaging system, subscribers observe topics and receive notifications when messages are published.
- Chat Applications: In a chat application, users observe changes in the chat room or conversation they are participating in. When new messages are sent or received, observers are notified, and the UI updates to display the new messages.
3.8 State
Different State Imple is going to gathering the related behaviours.
This seems a little heavy. But this is asuring simplity of imple of new state, otherwise there would be a prerequestion for previous code.
The state pattern is set to solve two main problems:[4]
- An object should change its behavior when its internal state changes.
- State-specific behavior should be defined independently. That is, adding new states should not affect the behavior of existing states.
The State Transition requires The Context Object, which holds reference of The State Objects, need be notified when transition required.
3.9 Strategy
Similar with The State, Strategy encapsulate the behaviours into separate derived imple, to keep the calling code reusability.
3.10 Template method
Template method pattern - Wikipedia
1 | The template method is a method in a superclass, usually an abstract superclass, and defines the skeleton of an operation in terms of a number of high-level steps. These steps are themselves implemented by additional *helper methods* in the same class as the *template method*. |
3.11 Visitor
Vistor与双分派 - lullaby (cheerlisten.com)
3.A1 Fluent interface
fluent interface is API style. Be Like
change the code from
1 |
|
to
1 | FluentGlutApp(argc, argv) |
3.A2 Specification
抽象业务逻辑过滤的规则: ISpecification
并通过一组CompositeSpecification
支持规则组合