The Template design pattern is about creating a skeleton in the base class and implementing functions differently in subclasses. In this example, BeverageMaker
calls functions boilWater
, brew
, and pourInCup
. Subclasses implement brew
differently depending on the behavior.
#include <iostream>
#include <string>
class BeverageMaker {
public:
void makeBeverage() {
std::cout << "=== Making " << getBeverageName() << " ===" << std::endl;
boilWater();
brew();
pourInCup();
if (wantsCondiments()) {
addCondiments();
}
std::cout << "โ
" << getBeverageName() << " is ready!" << std::endl;
std::cout << std::endl;
}
virtual ~BeverageMaker() = default;
protected:
void boilWater() {
std::cout << "๐ง Boiling water..." << std::endl;
}
void pourInCup() {
std::cout << "โ Pouring into cup..." << std::endl;
}
virtual void brew() = 0;
virtual void addCondiments() = 0;
virtual std::string getBeverageName() = 0;
virtual bool wantsCondiments() {
return true;
}
};
class CoffeeMaker : public BeverageMaker {
protected:
void brew() override {
std::cout << "โ Brewing coffee with hot water..." << std::endl;
}
void addCondiments() override {
std::cout << "๐ฅ Adding sugar and milk..." << std::endl;
}
std::string getBeverageName() override {
return "Coffee";
}
};
class TeaMaker : public BeverageMaker {
protected:
void brew() override {
std::cout << "๐ Steeping tea leaves..." << std::endl;
}
void addCondiments() override {
std::cout << "๐ Adding lemon and honey..." << std::endl;
}
std::string getBeverageName() override {
return "Tea";
}
};
int main() {
CoffeeMaker coffee;
coffee.makeBeverage();
TeaMaker tea;
tea.makeBeverage();
return 0;
}