第十六章:固本培元,守正出奇——Template Method的模板艺术
第十六章:固本培元,守正出奇——Template Method的模板艺术
风云再起,模板大师登场
在Command展示完他那精妙的命令艺术后,Template Method老成持重地走出,手持一卷蓝图。他的目光深邃而睿智,每个动作都透露出稳重与秩序。
"Command兄的请求封装确实精妙,"Template Method沉稳地说道,“但在算法结构固定、部分步骤需要变化的情况下,需要更加模板化的处理方式。诸位请看——”
Template Method展开手中的蓝图,蓝图上绘制着精密的算法结构:“我的模板方法模式,专为解决算法的统一框架与可变步骤问题而生!我定义算法的骨架,而将一些步骤延迟到子类中实现!”
架构老人眼中闪过赞许之色:“善!Template Method,就请你为大家展示这模板艺术的精妙所在。”
模板方法模式的核心要义
Template Method面向众人,开始阐述他的武学真谛:
“在我的模板方法模式中,主要包含两个核心概念:”
“模板方法:定义算法的骨架,由不可变的步骤和可被子类重写的钩子方法组成。”
“具体子类:实现算法中的特定步骤,但不能改变算法的整体结构。”
"其精妙之处在于,"Template Method继续道,“我遵循’好莱坞原则’——别调用我们,我们会调用你。父类控制着算法流程,只在需要时调用子类的方法。这样既保证了算法的稳定性,又提供了足够的灵活性!”
C++实战:饮料制作系统
"且让我以一个饮料制作系统为例,展示模板方法模式的实战应用。"Template Method说着,手中凝聚出一道道代码流光。
基础框架搭建
首先,Template Method定义了饮料制作的抽象基类:
#include <iostream>
#include <vector>
#include <string>
#include <memory>
#include <algorithm>
#include <map>
#include <iomanip>
#include <sstream>
#include <random>
#include <thread>
#include <chrono>// 抽象饮料类 - 模板方法模式的精髓
class Beverage {
public:virtual ~Beverage() = default;// 模板方法:定义饮料制作的算法骨架void prepareRecipe() {std::cout << "🍶 开始制作 " << getBeverageName() << "..." << std::endl;boilWater();brew();pourInCup();if (customerWantsCondiments()) {addCondiments();}// 钩子方法,子类可以选择性重写finalTouch();std::cout << "✅ " << getBeverageName() << " 制作完成!" << std::endl;std::cout << "🍽️ 描述: " << getDescription() << std::endl;}// 具体方法 - 由基类实现,子类共享void boilWater() {std::cout << "💧 煮沸水" << std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(500));}void pourInCup() {std::cout << "🥤 倒入杯中" << std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(200));}// 抽象方法 - 必须由子类实现virtual void brew() = 0;virtual void addCondiments() = 0;// 钩子方法 - 子类可以选择性重写virtual bool customerWantsCondiments() {return true; // 默认添加调料}virtual void finalTouch() {// 默认无额外操作}virtual std::string getBeverageName() const = 0;virtual std::string getDescription() const = 0;// 另一个模板方法:批量制作void prepareBatch(int count) {std::cout << "\n📦 批量制作 " << count << " 份 " << getBeverageName() << "..." << std::endl;for (int i = 1; i <= count; i++) {std::cout << "\n--- 第 " << i << " 份 ---" << std::endl;prepareRecipe();}std::cout << "🎉 批量制作完成!" << std::endl;}
};
具体子类实现
Template Method展示了各种饮料的具体实现:
// 具体类:茶
class Tea : public Beverage {
private:bool addLemon_;int steepTime_; // 浸泡时间(秒)public:Tea(bool addLemon = true, int steepTime = 3) : addLemon_(addLemon), steepTime_(steepTime) {std::cout << "🍃 初始化茶叶,浸泡时间: " << steepTime_ << "秒" << std::endl;}void brew() override {std::cout << "🫖 浸泡茶叶 " << steepTime_ << " 秒" << std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(steepTime_ * 200));}void addCondiments() override {if (addLemon_) {std::cout << "🍋 加入柠檬" << std::endl;} else {std::cout << "🍯 加入蜂蜜" << std::endl;}std::this_thread::sleep_for(std::chrono::milliseconds(200));}// 重写钩子方法bool customerWantsCondiments() override {// 茶总是添加调料return true;}void finalTouch() override {std::cout << "✨ 用茶匙轻轻搅拌" << std::endl;}std::string getBeverageName() const override {return addLemon_ ? "柠檬茶" : "蜂蜜茶";}std::string getDescription() const override {return "一杯香气扑鼻的" + std::string(addLemon_ ? "柠檬茶" : "蜂蜜茶") + ",浸泡时间" + std::to_string(steepTime_) + "秒";}// 茶特有的方法void setSteepTime(int time) {steepTime_ = time;std::cout << "⏱️ 设置茶叶浸泡时间: " << time << "秒" << std::endl;}
};// 具体类:咖啡
class Coffee : public Beverage {
private:bool addSugar_;bool addMilk_;std::string coffeeType_;public:Coffee(bool sugar = true, bool milk = false, const std::string& type = "阿拉比卡"): addSugar_(sugar), addMilk_(milk), coffeeType_(type) {std::cout << "☕ 初始化" << coffeeType_ << "咖啡豆" << std::endl;}void brew() override {std::cout << "🔨 用沸水冲泡咖啡粉" << std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(800));}void addCondiments() override {if (addSugar_ && addMilk_) {std::cout << "🥛 加入糖和牛奶" << std::endl;} else if (addSugar_) {std::cout << "🍬 加入糖" << std::endl;} else if (addMilk_) {std::cout << "🥛 加入牛奶" << std::endl;} else {std::cout << "⚫ 黑咖啡,不添加调料" << std::endl;}std::this_thread::sleep_for(std::chrono::milliseconds(300));}// 重写钩子方法bool customerWantsCondiments() override {// 咖啡默认添加调料,但可以被子类改变return addSugar_ || addMilk_;}void finalTouch() override {std::cout << "🎨 在咖啡表面拉花" << std::endl;}std::string getBeverageName() const override {std::string name = coffeeType_ + "咖啡";if (addSugar_ && addMilk_) name = "拿铁" + name;else if (addMilk_) name = "牛奶" + name;else if (addSugar_) name = "糖" + name;return name;}std::string getDescription() const override {return "一杯香醇的" + getBeverageName() + ",使用优质" + coffeeType_ + "咖啡豆";}// 咖啡特有的方法void setCoffeeType(const std::string& type) {coffeeType_ = type;std::cout << "🌱 更换咖啡豆种类: " << type << std::endl;}
};// 具体类:热巧克力
class HotChocolate : public Beverage {
private:bool withMarshmallows_;int chocolateIntensity_; // 1-5public:HotChocolate(bool marshmallows = true, int intensity = 3): withMarshmallows_(marshmallows), chocolateIntensity_(intensity) {std::cout << "🍫 准备巧克力粉,浓度级别: " << intensity << std::endl;}void brew() override {std::cout << "🥣 将巧克力粉与热水混合搅拌" << std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(600));}void addCondiments() override {if (withMarshmallows_) {std::cout << "🍡 加入棉花糖" << std::endl;}std::cout << "🥛 加入牛奶" << std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(300));}// 重写钩子方法void finalTouch() override {std::cout << "✨ 撒上少量可可粉装饰" << std::endl;}std::string getBeverageName() const override {return withMarshmallows_ ? "棉花糖热巧克力" : "经典热巧克力";}std::string getDescription() const override {return "一杯浓郁的热巧克力,巧克力浓度" + std::to_string(chocolateIntensity_) + "级" + (withMarshmallows_ ? ",配棉花糖" : "");}// 热巧克力特有的方法void setChocolateIntensity(int intensity) {chocolateIntensity_ = std::max(1, std::min(5, intensity));std::cout << "🍫 设置巧克力浓度: " << chocolateIntensity_ << "级" << std::endl;}
};// 具体类:无咖啡因茶 - 演示钩子方法的使用
class CaffeineFreeTea : public Tea {
private:bool noCondiments_;public:CaffeineFreeTea(bool noCondiments = false) : Tea(false, 2), noCondiments_(noCondiments) {std::cout << "🌿 使用无咖啡因茶叶" << std::endl;}// 重写钩子方法 - 控制是否添加调料bool customerWantsCondiments() override {if (noCondiments_) {std::cout << "🚫 顾客要求不添加任何调料" << std::endl;return false;}return Tea::customerWantsCondiments();}std::string getBeverageName() const override {return "无咖啡因" + Tea::getBeverageName();}std::string getDescription() const override {return "一杯温和的无咖啡因茶" + std::string(noCondiments_ ? ",无任何添加" : "");}
};
UML 武功秘籍图
实战演练:高级模板系统
Template Method继续展示更复杂的模板方法模式应用:
// 数据处理器模板基类
class DataProcessor {
public:virtual ~DataProcessor() = default;// 模板方法:数据处理流程void processData(const std::string& input) {std::cout << "\n🔄 开始处理数据..." << std::endl;// 记录开始时间auto startTime = std::chrono::high_resolution_clock::now();// 处理流程validateInput(input);auto parsedData = parseData(input);auto transformedData = transformData(parsedData);validateOutput(transformedData);saveResult(transformedData);// 记录结束时间auto endTime = std::chrono::high_resolution_clock::now();auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime);// 清理资源cleanup();std::cout << "✅ 数据处理完成,耗时: " << duration.count() << "ms" << std::endl;logProcessingStats();}// 具体方法void validateInput(const std::string& input) {std::cout << "🔍 验证输入数据..." << std::endl;if (input.empty()) {throw std::invalid_argument("输入数据不能为空");}std::this_thread::sleep_for(std::chrono::milliseconds(100));}void validateOutput(const std::string& output) {std::cout << "🔍 验证输出数据..." << std::endl;if (output.empty()) {throw std::runtime_error("输出数据为空,处理失败");}std::this_thread::sleep_for(std::chrono::milliseconds(100));}void cleanup() {std::cout << "🧹 清理处理过程中的临时资源..." << std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(50));}// 抽象方法virtual std::string parseData(const std::string& input) = 0;virtual std::string transformData(const std::string& data) = 0;virtual void saveResult(const std::string& result) = 0;// 钩子方法virtual void logProcessingStats() {std::cout << "📊 记录默认处理统计信息" << std::endl;}virtual bool enableDetailedLogging() {return false; // 默认关闭详细日志}
};// JSON数据处理器
class JsonDataProcessor : public DataProcessor {
private:int processedCount_;public:JsonDataProcessor() : processedCount_(0) {std::cout << "📄 创建JSON数据处理器" << std::endl;}std::string parseData(const std::string& input) override {std::cout << "🔧 解析JSON数据..." << std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(200));// 模拟JSON解析if (input.find('{') == std::string::npos) {throw std::runtime_error("无效的JSON格式");}return "Parsed: " + input;}std::string transformData(const std::string& data) override {std::cout << "🔄 转换JSON数据..." << std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(300));// 模拟数据转换return "Transformed: " + data + " [JSON->XML]";}void saveResult(const std::string& result) override {std::cout << "💾 保存JSON处理结果..." << std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(150));processedCount_++;}// 重写钩子方法void logProcessingStats() override {std::cout << "📊 JSON处理器统计: 已处理 " << processedCount_ << " 个文件" << std::endl;}bool enableDetailedLogging() override {return true; // JSON处理器启用详细日志}
};// CSV数据处理器
class CsvDataProcessor : public DataProcessor {
private:std::vector<std::string> processedFiles_;public:CsvDataProcessor() {std::cout << "📊 创建CSV数据处理器" << std::endl;}std::string parseData(const std::string& input) override {std::cout << "🔧 解析CSV数据..." << std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(150));// 模拟CSV解析if (input.find(',') == std::string::npos) {throw std::runtime_error("无效的CSV格式");}return "Parsed: " + input;}std::string transformData(const std::string& data) override {std::cout << "🔄 转换CSV数据..." << std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(250));// 模拟数据转换return "Transformed: " + data + " [CSV->JSON]";}void saveResult(const std::string& result) override {std::cout << "💾 保存CSV处理结果..." << std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(100));processedFiles_.push_back(result);}// 重写钩子方法void logProcessingStats() override {std::cout << "📊 CSV处理器统计: 已处理 " << processedFiles_.size() << " 个文件" << std::endl;}
};// 图像数据处理器
class ImageDataProcessor : public DataProcessor {
private:long long totalProcessedSize_;public:ImageDataProcessor() : totalProcessedSize_(0) {std::cout << "🖼️ 创建图像数据处理器" << std::endl;}std::string parseData(const std::string& input) override {std::cout << "🔧 解析图像数据..." << std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(400));// 模拟图像解析if (input.find("IMG") == std::string::npos) {throw std::runtime_error("无效的图像格式");}return "Parsed: " + input;}std::string transformData(const std::string& data) override {std::cout << "🔄 处理图像数据(调整大小、滤镜)..." << std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(600));// 模拟图像处理totalProcessedSize_ += data.length();return "Processed: " + data + " [Resized+Filtered]";}void saveResult(const std::string& result) override {std::cout << "💾 保存图像处理结果..." << std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(200));}// 重写钩子方法void logProcessingStats() override {std::cout << "📊 图像处理器统计: 总处理数据量 " << totalProcessedSize_ << " bytes" << std::endl;}bool enableDetailedLogging() override {return true; // 图像处理器启用详细日志}
};
模板方法模式的招式解析
招式一:多阶段处理模板
// 多阶段处理模板
class MultiStageProcessor {
public:virtual ~MultiStageProcessor() = default;// 模板方法:多阶段处理流程void executeProcess() {std::cout << "\n🚀 开始多阶段处理..." << std::endl;// 阶段1:准备if (!prepare()) {std::cout << "❌ 准备阶段失败,终止处理" << std::endl;return;}// 阶段2:预处理preProcess();// 阶段3:主处理(可能多次迭代)int iteration = 0;while (shouldContinue(iteration)) {std::cout << "\n🔄 迭代 " << (iteration + 1) << ":" << std::endl;mainProcess(iteration);iteration++;}// 阶段4:后处理postProcess();// 阶段5:完成finalize();std::cout << "✅ 多阶段处理完成" << std::endl;}protected:// 具体方法bool prepare() {std::cout << "📋 准备处理环境..." << std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(100));return true;}void finalize() {std::cout << "🎯 完成处理,释放资源..." << std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(50));}// 抽象方法virtual void preProcess() = 0;virtual void mainProcess(int iteration) = 0;virtual void postProcess() = 0;// 钩子方法virtual bool shouldContinue(int iteration) {return iteration < 3; // 默认执行3次迭代}virtual void onIterationComplete(int iteration) {std::cout << " ✅ 迭代 " << iteration << " 完成" << std::endl;}
};// 机器学习训练器
class MLTrainer : public MultiStageProcessor {
private:int maxEpochs_;double currentAccuracy_;public:MLTrainer(int maxEpochs = 10) : maxEpochs_(maxEpochs), currentAccuracy_(0.0) {std::cout << "🧠 创建机器学习训练器,最大轮次: " << maxEpochs_ << std::endl;}void preProcess() override {std::cout << "📊 加载训练数据..." << std::endl;std::cout << "🔧 初始化模型参数..." << std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(300));currentAccuracy_ = 0.1; // 初始准确率}void mainProcess(int iteration) override {std::cout << " 🎯 训练 epoch " << (iteration + 1) << "..." << std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(400));// 模拟训练过程currentAccuracy_ += 0.15 + (0.05 * (rand() % 10) / 10.0);currentAccuracy_ = std::min(0.95, currentAccuracy_);std::cout << " 📈 当前准确率: " << std::fixed << std::setprecision(3) << currentAccuracy_ * 100 << "%" << std::endl;onIterationComplete(iteration);}void postProcess() override {std::cout << "📐 评估最终模型性能..." << std::endl;std::cout << "💾 保存训练好的模型..." << std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(200));}// 重写钩子方法bool shouldContinue(int iteration) override {bool continueTraining = (iteration < maxEpochs_) && (currentAccuracy_ < 0.90);if (!continueTraining) {std::cout << "🏁 训练完成条件满足,停止训练" << std::endl;}return continueTraining;}void onIterationComplete(int iteration) override {std::cout << " ✅ Epoch " << (iteration + 1) << " 完成,准确率: " << std::fixed << std::setprecision(1) << (currentAccuracy_ * 100) << "%" << std::endl;}
};// 数据处理流水线
class DataPipeline : public MultiStageProcessor {
private:int dataSize_;int processedCount_;public:DataPipeline(int dataSize = 1000) : dataSize_(dataSize), processedCount_(0) {std::cout << "🏭 创建数据处理流水线,数据量: " << dataSize_ << std::endl;}void preProcess() override {std::cout << "🔧 初始化处理引擎..." << std::endl;std::cout << "📦 分配处理缓冲区..." << std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(250));}void mainProcess(int iteration) override {int batchSize = 100;int start = iteration * batchSize;int end = std::min(start + batchSize, dataSize_);std::cout << " 🏭 处理批次 " << (iteration + 1) << " (" << start << "-" << end << ")..." << std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(300));processedCount_ += (end - start);onIterationComplete(iteration);}void postProcess() override {std::cout << "📊 生成处理报告..." << std::endl;std::cout << "🧹 清理临时文件..." << std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(150));}// 重写钩子方法bool shouldContinue(int iteration) override {int batchSize = 100;return (iteration * batchSize) < dataSize_;}void onIterationComplete(int iteration) override {std::cout << " ✅ 批次 " << (iteration + 1) << " 完成,已处理: " << processedCount_ << "/" << dataSize_ << std::endl;}
};
招式二:带条件分支的模板
// 支持条件分支的模板
class ConditionalTemplateProcessor {
public:virtual ~ConditionalTemplateProcessor() = default;// 模板方法:支持条件分支的处理流程void processWithConditions() {std::cout << "\n🎛️ 开始条件模板处理..." << std::endl;// 阶段1:初始化initialize();// 阶段2:条件处理分支if (shouldUseAlternativeApproach()) {std::cout << "🔄 使用替代方法处理..." << std::endl;alternativeProcess();} else {std::cout << "🔄 使用标准方法处理..." << std::endl;standardProcess();}// 阶段3:条件优化if (needsOptimization()) {std::cout << "⚡ 执行优化步骤..." << std::endl;optimize();}// 阶段4:完成finalizeWithConditions();std::cout << "✅ 条件模板处理完成" << std::endl;}protected:// 具体方法void initialize() {std::cout << "🏁 初始化处理器..." << std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(100));}void finalizeWithConditions() {std::cout << "🏁 完成处理..." << std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(50));}// 抽象方法virtual void standardProcess() = 0;virtual void alternativeProcess() = 0;virtual void optimize() = 0;// 钩子方法 - 控制流程分支virtual bool shouldUseAlternativeApproach() {return false; // 默认使用标准方法}virtual bool needsOptimization() {return true; // 默认需要优化}virtual void onAlternativeSelected() {std::cout << " ℹ️ 选择替代处理方法" << std::endl;}virtual void onOptimizationApplied() {std::cout << " ℹ️ 优化已应用" << std::endl;}
};// 网络请求处理器
class NetworkRequestProcessor : public ConditionalTemplateProcessor {
private:bool useCache_;bool isSlowNetwork_;public:NetworkRequestProcessor(bool slowNetwork = false) : useCache_(false), isSlowNetwork_(slowNetwork) {std::cout << "🌐 创建网络请求处理器" << std::endl;}void standardProcess() override {std::cout << " 📡 发送标准网络请求..." << std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(isSlowNetwork_ ? 800 : 300));std::cout << " ✅ 收到响应" << std::endl;}void alternativeProcess() override {std::cout << " 💾 使用缓存策略..." << std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(100));std::cout << " ✅ 从缓存获取数据" << std::endl;useCache_ = true;}void optimize() override {if (useCache_) {std::cout << " ⚡ 优化缓存策略..." << std::endl;} else {std::cout << " ⚡ 压缩网络数据..." << std::endl;}std::this_thread::sleep_for(std::chrono::milliseconds(150));}// 重写钩子方法bool shouldUseAlternativeApproach() override {// 在网络慢时使用缓存策略if (isSlowNetwork_) {onAlternativeSelected();return true;}return false;}bool needsOptimization() override {// 总是需要优化return true;}void onAlternativeSelected() override {std::cout << " 📶 检测到慢速网络,启用缓存策略" << std::endl;}void onOptimizationApplied() override {std::cout << " 🚀 网络性能优化完成" << std::endl;}
};
完整测试代码
// 测试模板方法模式
void testTemplateMethodPattern() {std::cout << "=== 模板方法模式测试开始 ===" << std::endl;// 测试饮料制作系统std::cout << "\n--- 饮料制作系统测试 ---" << std::endl;std::cout << "\n🍵 测试茶制作:" << std::endl;Tea lemonTea(true, 4);lemonTea.prepareRecipe();std::cout << "\n☕ 测试咖啡制作:" << std::endl;Coffee blackCoffee(false, false, "哥伦比亚");blackCoffee.prepareRecipe();std::cout << "\n🍫 测试热巧克力制作:" << std::endl;HotChocolate chocolateWithMarshmallows(true, 4);chocolateWithMarshmallows.prepareRecipe();std::cout << "\n🌿 测试无咖啡因茶制作:" << std::endl;CaffeineFreeTea decafTea(true);decafTea.prepareRecipe();// 测试批量制作std::cout << "\n--- 批量制作测试 ---" << std::endl;Coffee batchCoffee(true, true, "巴西");batchCoffee.prepareBatch(3);std::cout << "\n=== 基础模板方法模式测试结束 ===" << std::endl;
}// 测试数据处理模板
void testDataProcessingTemplates() {std::cout << "\n=== 数据处理模板测试开始 ===" << std::endl;// 测试JSON处理器std::cout << "\n--- JSON数据处理测试 ---" << std::endl;JsonDataProcessor jsonProcessor;jsonProcessor.processData(R"({"name": "test", "value": 123})");// 测试CSV处理器std::cout << "\n--- CSV数据处理测试 ---" << std::endl;CsvDataProcessor csvProcessor;csvProcessor.processData("name,age,city\nJohn,25,New York");// 测试图像处理器std::cout << "\n--- 图像数据处理测试 ---" << std::endl;ImageDataProcessor imageProcessor;imageProcessor.processData("IMG_20230101_123456.jpg");std::cout << "\n=== 数据处理模板测试结束 ===" << std::endl;
}// 测试多阶段处理模板
void testMultiStageProcessing() {std::cout << "\n=== 多阶段处理模板测试开始 ===" << std::endl;// 测试机器学习训练器std::cout << "\n--- 机器学习训练测试 ---" << std::endl;MLTrainer mlTrainer(5);mlTrainer.executeProcess();// 测试数据处理流水线std::cout << "\n--- 数据处理流水线测试 ---" << std::endl;DataPipeline dataPipeline(350);dataPipeline.executeProcess();std::cout << "\n=== 多阶段处理模板测试结束 ===" << std::endl;
}// 测试条件分支模板
void testConditionalTemplates() {std::cout << "\n=== 条件分支模板测试开始 ===" << std::endl;// 测试正常网络情况std::cout << "\n--- 正常网络情况测试 ---" << std::endl;NetworkRequestProcessor normalProcessor(false);normalProcessor.processWithConditions();// 测试慢速网络情况std::cout << "\n--- 慢速网络情况测试 ---" << std::endl;NetworkRequestProcessor slowProcessor(true);slowProcessor.processWithConditions();std::cout << "\n=== 条件分支模板测试结束 ===" << std::endl;
}// 实战应用:智能饮料机系统
class SmartBeverageMachine {
private:std::map<std::string, std::unique_ptr<Beverage>> beverageRecipes_;std::vector<std::string> orderHistory_;public:SmartBeverageMachine() {std::cout << "🏪 创建智能饮料机" << std::endl;initializeRecipes();}void initializeRecipes() {// 初始化各种饮料配方beverageRecipes_["lemon_tea"] = std::make_unique<Tea>(true, 3);beverageRecipes_["honey_tea"] = std::make_unique<Tea>(false, 4);beverageRecipes_["black_coffee"] = std::make_unique<Coffee>(false, false, "巴西");beverageRecipes_["latte"] = std::make_unique<Coffee>(true, true, "哥伦比亚");beverageRecipes_["hot_chocolate"] = std::make_unique<HotChocolate>(true, 4);beverageRecipes_["decaf_tea"] = std::make_unique<CaffeineFreeTea>(false);std::cout << "✅ 初始化 " << beverageRecipes_.size() << " 种饮料配方" << std::endl;}void makeBeverage(const std::string& beverageId) {auto it = beverageRecipes_.find(beverageId);if (it != beverageRecipes_.end()) {std::cout << "\n🧃 制作饮料: " << beverageId << std::endl;it->second->prepareRecipe();orderHistory_.push_back(beverageId);} else {std::cout << "❌ 未知饮料类型: " << beverageId << std::endl;}}void makeCustomTea(bool withLemon, int steepTime) {std::cout << "\n🧃 制作定制茶..." << std::endl;Tea customTea(withLemon, steepTime);customTea.prepareRecipe();orderHistory_.push_back("custom_tea");}void showMenu() {std::cout << "\n📋 智能饮料机菜单" << std::endl;std::cout << "==================" << std::endl;std::cout << "1. 柠檬茶 (lemon_tea)" << std::endl;std::cout << "2. 蜂蜜茶 (honey_tea)" << std::endl;std::cout << "3. 黑咖啡 (black_coffee)" << std::endl;std::cout << "4. 拿铁 (latte)" << std::endl;std::cout << "5. 热巧克力 (hot_chocolate)" << std::endl;std::cout << "6. 无咖啡因茶 (decaf_tea)" << std::endl;std::cout << "7. 定制茶" << std::endl;}void showOrderHistory() {std::cout << "\n📜 订单历史 (" << orderHistory_.size() << " 杯):" << std::endl;for (size_t i = 0; i < orderHistory_.size(); ++i) {std::cout << " " << (i + 1) << ". " << orderHistory_[i] << std::endl;}}void runDemo() {std::cout << "\n🎮 运行智能饮料机演示..." << std::endl;std::cout << "=======================" << std::endl;showMenu();// 制作各种饮料makeBeverage("lemon_tea");makeBeverage("latte");makeBeverage("hot_chocolate");makeCustomTea(true, 5);// 批量制作std::cout << "\n--- 批量制作测试 ---" << std::endl;auto& coffee = beverageRecipes_["black_coffee"];if (coffee) {coffee->prepareBatch(2);}showOrderHistory();}
};// 高级应用:可配置模板系统
class ConfigurableTemplateSystem {
private:std::vector<std::unique_ptr<MultiStageProcessor>> processors_;public:ConfigurableTemplateSystem() {std::cout << "⚙️ 创建可配置模板系统" << std::endl;}void addProcessor(std::unique_ptr<MultiStageProcessor> processor) {processors_.push_back(std::move(processor));std::cout << "➕ 添加处理器,当前总数: " << processors_.size() << std::endl;}void runAllProcessors() {std::cout << "\n🚀 执行所有处理器..." << std::endl;for (size_t i = 0; i < processors_.size(); ++i) {std::cout << "\n--- 处理器 " << (i + 1) << " ---" << std::endl;processors_[i]->executeProcess();}std::cout << "\n🎉 所有处理器执行完成" << std::endl;}void runDemo() {std::cout << "\n🔧 运行可配置模板系统演示..." << std::endl;// 添加不同类型的处理器addProcessor(std::make_unique<MLTrainer>(8));addProcessor(std::make_unique<DataPipeline>(500));// 执行所有处理器runAllProcessors();}
};int main() {std::cout << "🌈 设计模式武林大会 - 模板方法模式演示 🌈" << std::endl;std::cout << "=========================================" << std::endl;// 测试基础模板方法模式testTemplateMethodPattern();// 测试数据处理模板testDataProcessingTemplates();// 测试多阶段处理模板testMultiStageProcessing();// 测试条件分支模板testConditionalTemplates();// 运行智能饮料机演示std::cout << "\n=== 智能饮料机系统演示 ===" << std::endl;SmartBeverageMachine beverageMachine;beverageMachine.runDemo();// 运行可配置模板系统演示std::cout << "\n=== 可配置模板系统演示 ===" << std::endl;ConfigurableTemplateSystem templateSystem;templateSystem.runDemo();// 交互式演示std::cout << "\n🎯 交互式模板方法演示" << std::endl;std::cout << "====================" << std::endl;std::vector<std::unique_ptr<Beverage>> demoBeverages;demoBeverages.push_back(std::make_unique<Tea>(true, 3));demoBeverages.push_back(std::make_unique<Coffee>(true, false, "埃塞俄比亚"));demoBeverages.push_back(std::make_unique<HotChocolate>(false, 5));for (auto& beverage : demoBeverages) {beverage->prepareRecipe();}std::cout << "\n🎉 模板方法模式演示全部完成!" << std::endl;return 0;
}
模板方法模式的武学心得
适用场景
- 算法结构固定:当多个类包含相同的算法结构,但某些步骤实现不同时
- 代码复用:当希望避免代码重复,将公共行为提取到父类时
- 控制子类扩展:当希望控制子类对算法的扩展方式时
- 框架设计:在框架中定义操作骨架,让用户填充具体实现时
优点
- 代码复用:将不变的行为移到父类,避免代码重复
- 控制反转:父类控制算法流程,子类只需实现特定步骤
- 符合开闭原则:可以增加新的具体子类而不影响现有代码
- 提高可维护性:算法修改只需在父类中进行
缺点
- 限制子类灵活性:子类必须遵循父类定义的算法骨架
- 可能违反里氏替换原则:如果子类修改了模板方法的流程
- 增加系统复杂度:每个不同的实现都需要一个子类
- 调试困难:模板方法中的控制流可能难以理解和调试
武林高手的点评
Strategy 赞叹道:“Template Method 兄的算法骨架设计确实精妙!能够如此优雅地统一算法结构同时允许步骤变化,这在需要固定流程的系统中确实无人能及。”
Factory Method 也点头称赞:“Template Method 兄专注于算法的模板化,而我更关注对象的创建。我们都涉及父类与子类的协作,但关注点不同。”
Template Method 谦虚回应:“诸位过奖了。每个模式都有其适用场景。在需要固定算法骨架但允许某些步骤变化时,我的模板方法模式确实能发挥重要作用。但在需要灵活创建对象时,Factory Method 兄的方法更加合适。”
下章预告
在Template Method展示完他那精妙的模板艺术后,Iterator 动作流畅、步履轻盈地走出。
“Template Method 兄的算法骨架确实精妙,但在集合遍历和元素访问方面,需要更加统一和优雅的方式。” Iterator 优雅地说道,“下一章,我将展示如何通过迭代器模式提供一种统一的方法来顺序访问集合中的元素,而又不暴露其底层表示!”
架构老人满意地点头:“善!集合的遍历访问确实是日常编程的常见需求。下一章,就请 Iterator 展示他的迭代艺术!”
欲知 Iterator 如何通过迭代器模式实现集合的统一遍历,且听下回分解!