背景与痛点
在后台管理系统中,我们经常遇到这样的场景:需要渲染多种不同类型的配置模块,每种模块有不同的:
- 数据结构
- 表格列配置
- 表单字段
- CRUD 操作逻辑
传统做法是用大量的 if-else 或 switch-case,导致代码臃肿、难以维护,因此我们想到了一种解决方案:策略模式+同意渲染器
定义
策略模式是一种行为设计模式,它定义了一系列算法,把它们封装起来,并使它们可以相互替换。
核心思想
❌ 不用策略模式:一堆 if-else / switch
✅ 用策略模式:把每种算法封装成独立的策略,按需选择
经典场景
根据用户输入类型判断是否符合标准
❌ 不用策略模式
1 |
|
问题:
- 函数越来越长
- 新增验证规则要改原函数
- 违反开闭原则
开闭原则:对扩展开放,对修改关闭(Open for extension, Closed for modification),意思是:软件实体(类、模块、函数)应该可以扩展新功能,但不应该修改已有代码。
✅ 使用策略模式
1 |
|
最佳实践
架构概览
1 | ┌─────────────────────────────────────────────────────────┐ |
定义策略接口
首先,抽象出所有模块共同的行为:
1 | // types.ts |
设计亮点
- 必选方法 vs 可选方法:match、transformDataSource、handleAdd 是必须的,而 handleDragEnd、customColumns 等是可选的
- 通过 context 参数传递额外数据,保持接口稳定
策略注册表
1 | // modules/index.ts |
设计亮点
- 顺序匹配,先匹配到的优先
- DefaultStrategy 作为兜底,match: () => true
- 新增模块类型只需添加新策略,无需修改现有代码
具体策略实现
1 | // DefaultModule.tsx - 兜底策略 |
1 | // UserAgreementModule.tsx - 特定策略 |
统一渲染器
1 | // ModuleRenderer.tsx |
设计优势
✅ 开闭原则 (OCP)
- 对扩展开放:新增模块类型只需创建新策略文件
- 对修改关闭:无需修改 ModuleRenderer 或其他策略
✅ 单一职责 (SRP)
- ModuleRenderer:只负责组装和协调
- 各 Strategy:只负责自己类型的具体逻辑
✅ 依赖倒置 (DIP)
- ModuleRenderer 依赖抽象的 ModuleStrategy 接口
- 不依赖具体的策略实现
✅ 可测试性
- 每个策略可以独立单元测试
- 渲染器逻辑与业务逻辑分离
扩展新模块类型
只需 3 步:
1 | // 1. 创建新策略文件 NewModuleStrategy.tsx |