Delphi:TList/TObjectList 设计中的 Notify 设计范式
在 Delphi 的 TList
/TObjectList
设计中,Notify
方法实现了经典的 观察者模式(Observer Pattern) 与 模板方法模式(Template Method Pattern) 的混合设计,下面是详细解析:
🔍 设计模式分析:复合型模式实现
1. 观察者模式(Observer Pattern)
-
核心思想:对象(Subject)状态变化时自动通知依赖对象(Observers)
-
在
Notify
中的体现:// TList (Subject) 内部操作流程 procedure TList.Delete(Index: Integer); beginItem := Get(Index); // 获取要删除的元素Notify(Item, lnDeleted); // ✅ 发送删除通知InternalDelete(Index); // 实际执行删除 end;
TList
作为 Subject(主题),在状态变更(元素删除)时主动调用Notify
TObjectList
作为 Observer(观察者),通过覆盖Notify
实现响应逻辑
2. 模板方法模式(Template Method Pattern)
-
核心思想:父类定义算法骨架,子类重写特定步骤
-
在继承链中的实现:
- 模板方法:
TList.Delete
/Insert
/Clear
包含固定流程(算法骨架) - 扩展点:
Notify
是预设的扩展钩子(hook),子类可定制行为 - 控制反转:
TList
控制流程,TObjectList
控制具体释放行为
- 模板方法:
⚙️ Notify 机制执行流程
💡 设计优势分析
1. 开闭原则(OCP)
- 对扩展开放:通过覆盖
Notify
,可添加自定义行为typeTLoggingObjectList = class(TObjectList)protectedprocedure Notify(Ptr: Pointer; Action: TListNotification); override;end;procedure TLoggingObjectList.Notify(...); beginif Action = lnAdded thenLog('添加对象: ' + TObject(Ptr).ClassName);inherited; // 保持核心释放行为 end;
- 对修改封闭:
TList
的核心算法永不改变
2. 单一职责原则(SRP)
类 | 职责 |
---|---|
TList | 管理集合数据结构(增删改查) |
TObjectList | 管理对象生命周期(仅通过 Notify 扩展) |
3. 控制反转(IoC)
// 基类控制流程
procedure TList.Clear;
beginwhile Count > 0 doDelete(Count - 1); // ➡️ 触发 Notify 调用
end;
子类不关心何时被调用,只专注 “当删除发生时该做什么”
⚠️ 关键设计决策
-
双向通讯机制
- 父类调用子类:
TList.Delete
→TObjectList.Notify
- 子类回调父类:
inherited Notify()
保持扩展性
- 父类调用子类:
-
按事件类型分发
TListNotification = (lnAdded, lnExtracted, lnDeleted);
不同的操作(Add/Delete/Extract)触发不同事件类型,实现精细控制
-
条件触发设计
if OwnsObjects and (Action = lnDeleted) then ...
通过布尔开关控制行为,避免资源管理冲突
🔥 对比原始设计差异
您给出的原始代码与现实中的 Delphi 实现略有不同:
实际 Delphi 实现(更严谨):
procedure TObjectList.Notify(Ptr: Pointer; Action: TListNotification);
begin// 仅在删除且拥有所有权时释放if (Action = lnDeleted) and FOwnsObjects thenTObject(Ptr).Free;// 关键:先处理再传递通知(避免父类操作已释放对象)inherited Notify(Ptr, Action);
end;
您提供代码的潜在风险:
// 错误顺序示例(您的代码):
beginif OwnsObjects then ... Free; // 先释放对象inherited Notify; // ⚠️ 父类可能操作已释放的内存
end;
🌟 总结:Notify 设计范式
- 模式类型:观察者模式(事件通知)+ 模板方法模式(可扩展算法框架)
- 设计目的:实现对象生命周期管理的正交扩展
- 行业应用:
- Delphi/C++ Builder 的 VCL/RTL 容器类
- Qt 的
QObject
事件系统 - .NET
Collection<T>
的虚方法保护
- 黄金法则:
“当需要扩展行为但不破坏封装时,用事件钩子代替直接修改”
—— 《设计模式:可复用面向对象软件的基础》