一、模板方法模式 — 固定流程可变细节基类定死流程步骤子类只填充其中的可变环节。C 实现 — 以数据导出为例代码语言cppAI代码解释class DataExporter { public: // 固定流程不可 override void Export(const std::string path) { auto data FetchData(); // 步骤 1获取数据固定 auto formatted Format(data); // 步骤 2格式化子类决定 WriteFile(path, formatted); // 步骤 3写文件固定 OnExportDone(path); // 步骤 4完成通知子类可选 } virtual ~DataExporter() default; protected: virtual std::string Format(const std::vectorRecord data) 0; // 必须实现 virtual void OnExportDone(const std::string path) {} // 可选钩子 private: std::vectorRecord FetchData() { /* 从数据库读 */ } void WriteFile(const std::string path, const std::string content) { /* 写磁盘 */ } }; class CsvExporter : public DataExporter { protected: std::string Format(const std::vectorRecord data) override { // 格式化为 CSV } }; class JsonExporter : public DataExporter { protected: std::string Format(const std::vectorRecord data) override { // 格式化为 JSON } void OnExportDone(const std::string path) override { NotifyUser(导出完成: path); } };前端类比代码语言typescriptAI代码解释// React 类组件 — 框架定义了 mount → render → didMount 的流程 // 你只填 render() 和 componentDidMount() // Express 的 res.send() 内部也是模板方法 // 设置 Content-Type → 序列化 body → 发送 → 触发 finish 事件关键点基类流程方法不加virtual不希望子类改流程钩子方法加virtual允许子类自定义有默认实现的钩子 可选覆盖 0纯虚 必须覆盖二、观察者模式 — 发布/订阅发布者不知道谁在监听订阅者不知道事件从哪来。C 实现 — 以消息总线为例代码语言cppAI代码解释class MessageBus { public: using Handler std::functionvoid(const std::string payload); int Subscribe(const std::string topic, Handler handler) { int id next_id_; topics_[topic].push_back({id, std::move(handler)}); return id; // 返回订阅 ID用于取消 } void Unsubscribe(int subscription_id) { for (auto [topic, subs] : topics_) { subs.erase(std::remove_if(subs.begin(), subs.end(), [subscription_id](auto s) { return s.id subscription_id; }), subs.end()); } } void Publish(const std::string topic, const std::string payload) { auto it topics_.find(topic); if (it topics_.end()) return; for (auto sub : it-second) { sub.handler(payload); } } private: struct Subscription { int id; Handler handler; }; std::unordered_mapstd::string, std::vectorSubscription topics_; int next_id_ 0; }; // 使用 MessageBus bus; int id bus.Subscribe(order.paid, [](const std::string data) { SendNotification(data); }); bus.Publish(order.paid, R({orderId: 123})); bus.Unsubscribe(id); // 必须手动取消前端类比代码语言typescriptAI代码解释// Node.js EventEmitter emitter.on(order.paid, handler); emitter.emit(order.paid, data); emitter.off(order.paid, handler);C 特有要点必须手动 Unsubscribe— JS 中 GC 回收对象时关联的闭包也会被回收C 不会。忘了取消 访问已销毁对象 崩溃返回订阅 ID— 比存 handler 指针更可靠std::function不支持比较三、策略模式 — 运行时切换算法同一个操作有多种实现方式运行时选一种。C 实现 — 以压缩策略为例代码语言cppAI代码解释class ICompressor { public: virtual std::vectoruint8_t Compress(const std::vectoruint8_t data) 0; virtual std::vectoruint8_t Decompress(const std::vectoruint8_t data) 0; virtual ~ICompressor() default; }; class GzipCompressor : public ICompressor { public: std::vectoruint8_t Compress(const std::vectoruint8_t data) override { /* gzip */ } std::vectoruint8_t Decompress(const std::vectoruint8_t data) override { /* gunzip */ } }; class LZ4Compressor : public ICompressor { public: std::vectoruint8_t Compress(const std::vectoruint8_t data) override { /* lz4 */ } std::vectoruint8_t Decompress(const std::vectoruint8_t data) override { /* lz4 */ } }; class FileStorage { public: FileStorage(std::unique_ptrICompressor compressor) : compressor_(std::move(compressor)) {} void Save(const std::string path, const std::vectoruint8_t data) { auto compressed compressor_-Compress(data); WriteToDisk(path, compressed); } private: std::unique_ptrICompressor compressor_; }; // 使用根据场景选择 auto storage FileStorage(std::make_uniqueLZ4Compressor()); // 速度优先 auto storage2 FileStorage(std::make_uniqueGzipCompressor()); // 体积优先前端类比代码语言typescriptAI代码解释// 根据环境选择不同的存储策略 const storage isServer ? new FileSystemStorage() : new LocalStorageAdapter(); storage.save(key, data);优势新增压缩算法如 Zstd只需新增一个类不改已有代码策略可通过配置文件/环境变量决定无需重新编译四、责任链模式 — 逐层尝试处理请求沿链传递每个节点决定我处理或交给下一个。C 实现 — 以日志级别过滤为例代码语言cppAI代码解释class LogHandler { public: enum Level { DEBUG, INFO, WARN, ERROR }; LogHandler(Level level) : level_(level) {} void SetNext(std::shared_ptrLogHandler next) { next_ next; } void Log(Level level, const std::string msg) { if (level level_) { Write(level, msg); } if (next_) { next_-Log(level, msg); } } virtual ~LogHandler() default; protected: virtual void Write(Level level, const std::string msg) 0; private: Level level_; std::shared_ptrLogHandler next_; }; class ConsoleLogger : public LogHandler { public: ConsoleLogger() : LogHandler(DEBUG) {} protected: void Write(Level level, const std::string msg) override { std::cout [ level ] msg std::endl; } }; class FileLogger : public LogHandler { public: FileLogger() : LogHandler(WARN) {} // 只记录 WARN 以上 protected: void Write(Level level, const std::string msg) override { // 写入日志文件 } }; class AlertLogger : public LogHandler { public: AlertLogger() : LogHandler(ERROR) {} // 只报警 ERROR protected: void Write(Level level, const std::string msg) override { SendAlert(msg); } }; // 组装链 auto console std::make_sharedConsoleLogger(); auto file std::make_sharedFileLogger(); auto alert std::make_sharedAlertLogger(); console-SetNext(file); file-SetNext(alert); // 使用 console-Log(ERROR, Database connection lost); // → ConsoleLogger 输出 → FileLogger 记录 → AlertLogger 报警前端类比代码语言typescriptAI代码解释// Express 中间件 — 经典责任链 app.use(corsMiddleware); // 处理跨域然后 next() app.use(authMiddleware); // 处理鉴权然后 next() app.use(routerMiddleware); // 处理路由和模板方法的区别模板方法固定的步骤 1→2→3→4每步做什么由子类决定责任链不确定谁来处理按顺序问过去谁能处理谁处理五、命令模式 — 操作的记录与回放把操作封装为对象可以存储、撤销、重做。C 实现 — 以文本编辑器为例代码语言cppAI代码解释class ICommand { public: virtual void Execute() 0; virtual void Undo() 0; virtual ~ICommand() default; }; class InsertTextCommand : public ICommand { public: InsertTextCommand(Document doc, int pos, const std::string text) : doc_(doc), pos_(pos), text_(text) {} void Execute() override { doc_.Insert(pos_, text_); } void Undo() override { doc_.Delete(pos_, text_.size()); } private: Document doc_; int pos_; std::string text_; }; class DeleteTextCommand : public ICommand { public: DeleteTextCommand(Document doc, int pos, int length) : doc_(doc), pos_(pos), length_(length) {} void Execute() override { deleted_text_ doc_.GetText(pos_, length_); // 记住被删的内容 doc_.Delete(pos_, length_); } void Undo() override { doc_.Insert(pos_, deleted_text_); } private: Document doc_; int pos_, length_; std::string deleted_text_; }; class CommandHistory { public: void Execute(std::unique_ptrICommand cmd) { cmd-Execute(); history_.push_back(std::move(cmd)); redo_stack_.clear(); } void Undo() { if (history_.empty()) return; auto cmd std::move(history_.back()); history_.pop_back(); cmd-Undo(); redo_stack_.push_back(std::move(cmd)); } void Redo() { if (redo_stack_.empty()) return; auto cmd std::move(redo_stack_.back()); redo_stack_.pop_back(); cmd-Execute(); history_.push_back(std::move(cmd)); } private: std::vectorstd::unique_ptrICommand history_; std::vectorstd::unique_ptrICommand redo_stack_; };前端类比代码语言typescriptAI代码解释// Redux 本质就是命令模式 dispatch({ type: INSERT_TEXT, pos: 5, text: hello }); // 命令对象 // Redux DevTools Time Travel 命令回放/撤销适用场景场景怎么用编辑器撤销/重做每个操作是一个 CommandUndo 执行反操作宏录制记录一系列命令一键回放事务多个命令组成一组失败时全部 Undo操作日志序列化命令到磁盘用于审计或 Bug 复现总结模式核心问题C 关键实现前端等价物模板方法统一流程可变细节虚函数钩子 非虚流程方法React 生命周期观察者事件解耦订阅 ID 手动取消EventEmitter策略算法可替换接口 unique_ptr条件选择不同实现责任链逐层尝试链表传递Express 中间件命令操作可撤销/回放Execute Undo 封装Redux Action