【声明】本题目来源于卡码网(题目页面 (kamacoder.com))
【提示:如果不想看文字介绍,可以直接跳转到C++编码部分】
? ? ? ? --什么是模板方法模式(第18种设计模式)
? ? ? ? 模板方法模式(Template Method Pattern)是?种行为型设计模式, 它定义了?个算法的骨架,将?些步骤的实现延迟到?类。模板方法模式使得?类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
????????举个简单的例?,做?道菜通常都需要包含?少三步:
????????不同菜品的亨饪过程是不?样的,但是我们可以先定义?个”?架”,包含这三个步骤,亨饪过程的过程放到具体的炒菜类中去实现,这样,?论炒什么菜,都可以沿?相同的炒菜算法,只需在?类中实现具体的炒菜步骤,从而提?了代码的复?性。
????????模板?法模式的基本结构包含以下两个角色:
????????模板?法模式的简单示例如下:先以Java代码作以说明
1. 定义模板类,包含模板?法,定义了算法的?架, ?般都加上final 关键字(C++为 const关键字),避免子类重写。
// 模板类
abstract class AbstractClass {
// 模板?法,定义了算法的?架
public final void templateMethod() {
step1();
step2();
step3();
}
// 抽象?法,由?类实现
protected abstract void step1();
protected abstract void step2();
protected abstract void step3();
}
2. 定义具体类, 实现模板类中的抽象?法
// 具体类
class ConcreteClass extends AbstractClass {
@Override
protected void step1() {
System.out.println("Step 1 ");
}
@Override
protected void step2() {
System.out.println("Step 2 ");
}
@Override
protected void step3() {
System.out.println("Step 3");
}
}
3. 客户端实现
/**
* @version Copyright (c) 2024 NCDC, Servo。 Unpublished - All rights reserved
* @file TemplateMethodMode.hpp
* @brief 模板方法模式
* @autor 写代码的小恐龙er
* @date 2024/01/20
*/
public class Main {
public static void main(String[] args) {
AbstractClass concreteTemplate = new ConcreteClass();
// 触发整个算法的执?
concreteTemplate.templateMethod();
}
}
????????模板?法模式将算法的不变部分被封装在模板?法中,而可变部分算法由?类继承实现,这样做可以很好的提?代码的复?性,但是当算法的框架发?变化时,可能需要修改模板类,这也会影响到所有的?类。
????????总体来说,当算法的整体步骤很固定,但是个别步骤在更详细的层次上的实现可能不同时,通常考虑模板?法模式来处理。在已有的?具和库中, Spring框架中的JdbcTemplate 类使?了模板?法模式,其中定义了?些执?数据库操作的模板?法,具体的数据库操作由回调函数提供。?在Java的JDK源码中, AbstractList 类也使?了模板?法模式,它提供了?些通用的?法,其中包括?些模板?法。具体的列表操作由?类实现。
1. 题目描述
????????小明喜欢品尝不同类型的咖啡,她发现每种咖啡的制作过程有一些相同的步骤,他决定设计一个简单的咖啡制作系统,使用模板方法模式定义咖啡的制作过程。系统支持两种咖啡类型:美式咖啡(American Coffee)和拿铁(Latte)。
????????咖啡制作过程包括以下步骤:
????????1.?研磨咖啡豆 Grinding coffee beans
????????2. 冲泡咖啡 Brewing coffee
????????3. 添加调料?Adding condiments
????????其中,美式咖啡和拿铁的调料添加方式略有不同, 拿铁在添加调料时需要添加牛奶Adding milk。
2. 输入描述
????????多行输入,每行包含一个数字,表示咖啡的选择(1 表示美式咖啡,2 表示拿铁)。
3. 输出描述
????????根据每行输入,输出制作咖啡的过程,包括咖啡类型和各个制作步骤,末尾有一个空行。
4. C++编码实例
/**
* @version Copyright (c) 2024 NCDC, Servo。 Unpublished - All rights reserved
* @file TemplateMethodMode.hpp
* @brief 模板方法模式
* @autor 写代码的小恐龙er
* @date 2024/01/20
*/
#include <iostream>
#include <string>
#include <vector>
using namespace std;
// 前置声明
// 抽象模板类 -- 包含模板?法,定义了算法的?架, ?般都加上final 关键字,避免?类重写
class CoffeeMaker;
// 实现具体类 -- 美式
class AmericanCoffeeMaker;
// 实现具体类 -- 拿铁
class LatteCoffeeMaker;
// 类的定义
// 抽象模板类
class CoffeeMaker
{
// 成员接口函数
public:
// 框架接口函数
const void TemplateCoffeeMethod(){
// 步骤一
GrindingCoffeeBeans();
// 步骤二
BrewingCoffee();
// 步骤三
AddingCondiments();
// 空行
std::cout << endl;
}
// 研磨咖啡豆工序
virtual void GrindingCoffeeBeans() = 0;
// 冲泡咖啡工序
virtual void BrewingCoffee() = 0;
// 添加调料工序
virtual void AddingCondiments(){
std::cout << "Adding condiments" << endl;
}
};
// 实现具体类 -- 美式
class AmericanCoffeeMaker : public CoffeeMaker
{
// 成员数据
private:
string _coffeeName;
// 成员接口函数重载
public:
// 构造函数
AmericanCoffeeMaker(string name){
this->_coffeeName = name;
std::cout<< "Making " << _coffeeName << ":"<<endl;
}
// 研磨咖啡豆工序 重载
void GrindingCoffeeBeans() override {
std::cout << "Grinding coffee beans" << endl;
}
// 冲泡咖啡工序 重载
void BrewingCoffee() override {
std::cout << "Brewing coffee" << endl;
}
};
// 实现具体类 -- 拿铁
class LatteCoffeeMaker : public CoffeeMaker
{
// 成员数据
private:
string _coffeeName;
// 成员接口函数重载
public:
// 构造函数
LatteCoffeeMaker(string name){
this->_coffeeName = name;
std::cout<< "Making " << _coffeeName << ":"<<endl;
}
// 研磨咖啡豆工序 重载
void GrindingCoffeeBeans() override {
std::cout << "Grinding coffee beans" << endl;
}
// 冲泡咖啡工序 重载
void BrewingCoffee() override {
std::cout << "Brewing coffee" << endl;
}
// 添加调料工序 重载
void AddingCondiments() override {
std::cout << "Adding milk" << endl;
std::cout << "Adding condiments" << endl;
}
};
// 客户端代码
int main()
{
// 输入的咖啡制作类型
int type = 0;
// 构造抽象模板类
CoffeeMaker *coffee = nullptr;
while(std::cin >> type){
if(type == 1){
coffee = new AmericanCoffeeMaker("American Coffee");
}
else if(type == 2){
coffee = new LatteCoffeeMaker("Latte");
}
else break;
// 开始统一制作咖啡
coffee->TemplateCoffeeMethod();
}
// 析构
if(coffee != nullptr){
delete coffee;
coffee = nullptr;
}
return 0;
}
......
To be continued.