第十六章:固本培元,守正出奇——Template Method的模板艺术 - 教程

news/2025/10/21 15:13:35/文章来源:https://www.cnblogs.com/tlnshuju/p/19155445

第十六章:固本培元,守正出奇——Template Method的模板艺术 - 教程

2025-10-21 15:08  tlnshuju  阅读(0)  评论(0)    收藏  举报

第十六章:固本培元,守正出奇——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-5
public:
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 武功秘籍图

«abstract»
Beverage
+prepareRecipe() : void
+boilWater() : void
+pourInCup() : void
+brew() : void
+addCondiments() : void
+customerWantsCondiments() : bool
+finalTouch() : void
+getBeverageName() : string
+getDescription() : string
+prepareBatch(int) : void
Tea
-bool addLemon_
-int steepTime_
+brew() : void
+addCondiments() : void
+customerWantsCondiments() : bool
+finalTouch() : void
+getBeverageName() : string
+getDescription() : string
+setSteepTime(int) : void
Coffee
-bool addSugar_
-bool addMilk_
-string coffeeType_
+brew() : void
+addCondiments() : void
+customerWantsCondiments() : bool
+finalTouch() : void
+getBeverageName() : string
+getDescription() : string
+setCoffeeType(string) : void
HotChocolate
-bool withMarshmallows_
-int chocolateIntensity_
+brew() : void
+addCondiments() : void
+finalTouch() : void
+getBeverageName() : string
+getDescription() : string
+setChocolateIntensity(int) : void
CaffeineFreeTea
-bool noCondiments_
+customerWantsCondiments() : bool
+getBeverageName() : string
+getDescription() : string

实战演练:高级模板系统

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 如何通过迭代器模式实现集合的统一遍历,且听下回分解!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/942310.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

实用指南:点鼠标左键一下变两下怎么回事?真相和解决方案

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

设计模式(C++)详解——策略模式(2) - 指南

设计模式(C++)详解——策略模式(2) - 指南pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "…

粗略写一个计算器 实现加减乘除 - I

//作业:写一个计算器,要求实现加减乘除功能,并且能够循环接受新的数据,通过用户交互实现 package com.zhang.method;import java.util.Scanner;public class homeworkDemo {public static void main(String[] args…

WPF使用MediaCapture开发相机应用(三、相机拍照)

上期弄好了相机的预览功能,现在可以进行拍照了。对上期有疑惑的点这里。 MediaCapture的教程是用UWP写的,教程里拍照是用MediaCapture.CapturePhotoToStorageFileAsync方法,老实说我研究了好久都没搞明白WPF什么创建…

2025年磨粉机厂家权威推荐榜:雷蒙磨粉机/环辊磨粉机/摆式磨粉机/矿石磨粉机/超细磨粉机/高压磨粉机,专业实力与高效生产之选

2025年磨粉机厂家权威推荐榜:雷蒙磨粉机/环辊磨粉机/摆式磨粉机/矿石磨粉机/超细磨粉机/高压磨粉机,专业实力与高效生产之选 在工业制造领域,磨粉设备作为物料加工的核心装备,其技术水平直接影响着生产效率和产品质…

我的第一份开源贡献:小米工程师程赛的社区之旅

打开链接点亮社区Star,照亮技术的前进之路。每一个点赞,都是社区技术大佬前进的动力Github 地址: https://github.com/secretflow/secretflow他是从校园走进开源世界的年轻工程师; 他在小米工作,却把开源当成生活…

2025陶瓷过滤机实力厂家推荐,铜陵杰达机械专注固液分离设备制造

2025陶瓷过滤机实力厂家推荐,铜陵杰达机械专注固液分离设备制造 固液分离领域的技术挑战与创新突破 在当前的工业生产中,固液分离设备作为关键环节,面临着诸多技术挑战。根据行业数据显示,传统过滤设备在处理微细颗…

2025信息流代运营公司推荐:线尚网络专注效果营销与品牌增长

2025信息流代运营公司推荐:线尚网络专注效果营销与品牌增长 信息流代运营领域面临的技术挑战 随着数字营销进入深水区,信息流代运营行业正面临前所未有的技术挑战。据行业数据显示,超过67%的企业在信息流广告投放中…

2025冷链解冻设备厂家推荐广东科恩,专业定制高湿静电解冻方案

2025冷链解冻技术新突破:专业定制高湿静电解冻方案引领行业变革 在食品工业快速发展的今天,解冻设备作为冷链环节中的重要组成部分,其技术水平直接影响着食品品质与安全。随着2025年的临近,冷链解冻设备行业正迎来…

SecureCRT 批量创建会话-cnblog

SecureCRT 批量创建会话 前言: 在使用CRT的过程中,如果需要创建大量的会话连接 如:使用telnet连接ensp的网络设备 如:一次性需要连接多台linux主机 开篇: 下载SecureCRT:https://www.vandyke.com/download/ 这里…

2025干燥设备厂家权威推荐:常州亿干专业定制实验室喷雾与真空耙式干燥机

2025干燥设备厂家权威推荐:常州亿干专业定制实验室喷雾与真空耙式干燥机 一、干燥设备行业面临的技术挑战 在当今工业生产领域,干燥设备作为关键工艺装备,其技术水平直接影响着产品质量和生产效率。小型喷雾干燥机、…

2025磨粉机厂家权威推荐:海城八里镇机械厂专注矿石超细研磨设备制造

2025磨粉机厂家权威推荐:海城八里镇机械厂专注矿石超细研磨设备制造 行业技术挑战与创新需求 在当前的工业制造领域,磨粉设备的技术革新正面临着前所未有的挑战。随着矿产资源的深度开发和精细化加工需求的提升,传统…

Vue技术之Vxe-Table的虚拟滚动

虚拟滚动 纵向虚拟滚动:scroll-y 横向虚拟滚动:scroll-x 1.首先留意项目中使用的版本,我这边在项目用的是"vxe-pc-ui": "4.0.95"版本"vxe-table": "4.7.65"版本 所以scrol…

实用指南:一次借助ChatGPT抵御恶意攻击的经历,为个人服务器添加自动防御系统Fail2ban

实用指南:一次借助ChatGPT抵御恶意攻击的经历,为个人服务器添加自动防御系统Fail2banpre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important;…

Docker补充

Docker知识点学习。目录Docker实际应用docker 管理镜像操作容器操作Dockerfile命令学习一些Docker的图解 Docker实际应用 docker 管理 镜像操作搜索对应镜像docker serarch xxx查看现有镜像docker images docker imag…

【QNX】Socket ServerClient 源代码

1 Socket Server 源代码 服务端计划只启动一个线程,所以功能实现时使用了一些全局变量。1 int32_t skt_s_listen_fd{-1};2 pthread_t thr_server;3 struct sockaddr_un srv_addr;4 struct sockaddr_un cli_addr;5 std…

Linux环境--文件系统--动静态库

Linux环境--文件系统--动静态库2025-10-21 14:44 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !importa…

详细介绍:大模型落地的四大核心引擎:从技术突破到产业重构

详细介绍:大模型落地的四大核心引擎:从技术突破到产业重构pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Conso…