16. 模板方法模式(Template Method)
16. 模板方法模式(Template Method)
问题:多个流程有相同的骨架,只有个别步骤不同。
核心:父类定义算法骨架,子类实现具体步骤。
type UserRecord = { name: string; age: number };
abstract class DataParser<T> {
parse(): void {
const raw = this.read();
const data = this.process(raw);
this.output(data);
}
protected abstract read(): string;
protected abstract process(raw: string): T;
protected output(data: T): void { console.log(`结果: ${JSON.stringify(data)}`); }
}
class JSONParser extends DataParser<UserRecord> {
protected read(): string { return '{"name":"小明","age":25}'; }
protected process(raw: string): UserRecord { return JSON.parse(raw) as UserRecord; }
}
class CSVParser extends DataParser<UserRecord> {
protected read(): string { return '小明,25'; }
protected process(raw: string): UserRecord {
const [name, age] = raw.split(',');
return { name, age: Number(age) };
}
}
new JSONParser().parse(); // 结果: {"name":"小明","age":25}
new CSVParser().parse(); // 结果: {"name":"小明","age":25}package template
import (
"encoding/json"
"fmt"
"strings"
)
type DataParser interface {
Read() string
Process(raw string) any
}
func Parse(p DataParser) {
raw := p.Read()
data := p.Process(raw)
fmt.Printf("结果: %v\n", data)
}
type JSONParser struct{}
func (j JSONParser) Read() string {
return `{"name":"小明","age":25}`
}
func (j JSONParser) Process(raw string) any {
var result map[string]any
json.Unmarshal([]byte(raw), &result)
return result
}
type CSVParser struct{}
func (c CSVParser) Read() string { return "小明,25" }
func (c CSVParser) Process(raw string) any {
parts := strings.Split(raw, ",")
return map[string]any{"name": parts[0], "age": parts[1]}
}实战场景
- 数据导入流程:读取文件、解析数据、校验字段、写入数据库、生成报告是固定骨架,不同文件类型只改解析步骤。
- 支付流程:创建订单、调用渠道、校验回调、更新状态、通知用户固定,渠道差异放到子步骤。
- 构建流程:安装依赖、编译、测试、打包、发布是骨架,不同项目重写其中某些步骤。
- 页面渲染流程:加载数据、鉴权、构造 props、渲染模板固定,不同页面实现自己的数据和模板。
- 爬虫任务:请求页面、解析内容、去重、存储、限速固定,不同站点只实现 URL 和解析逻辑。
- 机器学习训练:加载数据、预处理、训练、评估、保存模型固定,不同模型替换其中几步。
- 报表生成:查询数据、聚合、套模板、导出、发送固定,不同报表重写查询和模板。
- 表单提交:收集数据、校验、转换、提交、处理错误固定,不同表单提供字段和规则。
- 游戏关卡加载:加载资源、初始化角色、设置地图、注册事件固定,不同关卡只替换配置和脚本。
- CLI 命令执行:解析参数、校验环境、执行核心动作、输出结果固定,不同命令只重写核心动作。