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;
}