喝杯茶就能学会的设计模式 —— 模板方法模式

369 阅读5分钟

在这个快节奏的世界里,一杯热腾腾的茶不仅仅能舒缓身心,还能成为理解复杂编程概念的灵感源泉。今天,我们就在这份静谧与温暖中,通过泡茶这一日常活动,轻松掌握设计模式中的经典——模板方法模式。

泡茶与编程:看似不相干,实则紧密相连

想象一下,泡茶的过程就像是编写一个程序:每个步骤都是精心策划的指令,共同完成一个任务。从烧水到加入柠檬,每一步都不可或缺,正如软件开发中的各个环节。那么,如何让这个过程变得既高效又易于维护呢?这就需要引入模板方法模式的概念。

什么是模板方法模式?

模板方法模式是一种行为设计模式,它定义了一个操作中的算法骨架,将不变的部分放在超类中,可变的部分留给子类去实现。简而言之,就是提供一个固定的流程框架,但具体实现细节交由子类决定。就像泡茶的流程固定,但选择什么茶叶、是否加糖等细节可以自由变化。

泡茶的模板方法

让我们以泡茶为例,具体看看模板方法模式是如何运作的。泡茶的步骤可以抽象为以下几个环节:

  1. 准备材料:确保有水、茶叶和杯子。
  2. 加热:把水煮沸。
  3. 冲泡:用沸水冲泡茶叶。
  4. 装杯:将茶水倒入杯子。
  5. 个性化调整:根据个人喜好添加柠檬或其他配料。

代码实现

伪代码

  1. 构造函数 Tea(type): 定义了一个构造函数,接受一个参数 type,代表茶的类型。在构造函数内部,通过 this.type = type 设置实例的茶类型,并打印出准备泡制的茶的类型信息。

    function Tea(type) {    
                this.type = type;   
                console.log('您准备泡一杯' + this.type);  
            }
    
  2. 原型方法:

    • boilWater(): 定义在 Tea.prototype 上,描述了把水煮沸的步骤。
    • steepTeaBag(): 同样定义在原型上,描述了用沸水浸泡茶叶的步骤。
    • pourInCup(): 描述了把茶水倒进杯子的动作。
    • addLemon(): 个性化步骤,根据个人口味添加柠檬。 这些方法通过原型链共享,任何 Tea 的实例都可以访问到它们。
    Tea.prototype.boilWater = function() {
                console.log('把水煮沸');
            }   // 使用prototype 将方法添加到原型中 
            Tea.prototype.steepTeaBag = function() {
                console.log('用沸水浸泡茶叶');
            }   
            Tea.prototype.pourInCup = function() {
                console.log('把茶水倒进杯子');
            }
            Tea.prototype.addLemon = function() {
                console.log('根据个人口味添加柠檬');    
            }
    
  3. 模板方法 init(): 在 Tea.prototype 上定义了一个模板方法,它按照一定的顺序调用了前面定义的步骤方法,形成了泡茶的标准流程。

    Tea.prototype.init = function(){
                this.boilWater();
                this.steepTeaBag();
                this.pourInCup();
                this.addLemon();    
            }
    
  4. 创建实例 lemonTea: 通过 new Tea('柠檬茶') 创建了一个 Tea 的实例,传入 '柠檬茶' 作为茶的类型。

    var lemonTea = new Tea('柠檬茶');
    
  5. 调用 init() 方法: 对 lemonTea 实例调用 init() 方法,触发整个泡茶流程的执行。。

       lemonTea.init();    // 调用init方法,执行模板方法
    

完整代码呈现

 function Tea(type) {    
            this.type = type;   
            console.log('您准备泡一杯' + this.type);  
        }
        // prototype 是js的一个特殊属性,指向原型对象
        // 给Tea添加一个方法 对象prototype
        Tea.prototype.boilWater = function() {
            console.log('把水煮沸');
        }   // 使用prototype 将方法添加到原型中 
        Tea.prototype.steepTeaBag = function() {
            console.log('用沸水浸泡茶叶');
        }   
        Tea.prototype.pourInCup = function() {
            console.log('把茶水倒进杯子');
        }
        Tea.prototype.addLemon = function() {
            console.log('根据个人口味添加柠檬');    
        }   
        // 接口 模板方法接口。
        Tea.prototype.init = function(){
            this.boilWater();
            this.steepTeaBag();
            this.pourInCup();
            this.addLemon();    
        } 
        var lemonTea = new Tea('柠檬茶');
            
        lemonTea.init();    // 调用init方法,执行模板方法 

结果

image.png

使用模板方法模式的优势

  • 代码复用:通过在Tea构造函数的原型(prototype)上定义通用的泡茶步骤(如烧水、泡茶包、倒进杯子、加柠檬),所有茶的子类可以复用这些基本步骤,无需在每个子类中重复编写相同的代码。
  • 灵活性:虽然这个示例中没有展示子类重写父类方法的情况,但模板方法模式允许子类覆盖或补充父类中的某些步骤。

与AIGC的融合

在AI生成内容(AIGC)日益普及的今天,模板方法模式的价值更为凸显,其价值得到了进一步的强调和提升。这种模式通过定义一个操作中的算法骨架,并允许子类重定义某些步骤,为AI生成的内容提供了结构化和可定制的框架。

代码示例

运用OpenAI API与ChatGPT模型来处理和生成文本内容。它首先配置了OpenAI客户端连接到一个特定的API基础URL,随后定义了一个异步函数getChatResponse来与ChatGPT交互,传入模型名和提示信息,以获取AI生成的回复。脚本将一段关于泡茶的自然语言描述转换成步骤化的指令。

require('dotenv').config(); 
const OpenAI = require('openai');
const client = new OpenAI({
    apiKey: process.env.OPENAI_KEY,
    baseURL: 'https://api.chatanywhere.tech/v1/',  
}); 
const getChatResponse = async function(model, prompt){//openAI 的聊天接口
    const response = await client.chat.completions.create({
        model: model,   
        messages:[{
        role:"user"  ,
        content: prompt,
    }]
    })
    return response.choices[0].message.content; 
}

const main = async () => {
    // AIGC 优势就是处理文本, 生成内容
    const text = `
        泡一杯茶很容易。首先,需要把水烧开。在等待期间,拿一个杯子
        并把茶包放进去。 一旦水开了,就把他倒在茶包上。等待一会儿,
        让茶叶浸泡,几分钟后,取出茶包。如果你愿意,可以加一些糖
        或者牛奶调味。就这样,您可以享受一杯美味的茶了。
    `
    const prompt = `
    您将获得由三个引号括起来的文本
    如果它包含一系列的指令,需要按照以下格式重新编写这些指令。

    第一步 - ...
    第二步 - ...
    ...
    第N步 - ...
    如果文本中不包含一些系列的指令,则直接写"未提供步骤"
    """${text}"""   
    `
    const result = await getChatResponse("gpt-3.5-turbo",prompt); 
    console.log(result);     
};  
main();

结果

image.png

结语

如同泡茶时那一缕升腾的热气,模板方法模式在软件开发中同样散发出智慧的光芒。它教会我们如何在不变的框架下拥抱变化,如何在繁复的代码中寻求简洁与优雅。在这个AI与传统编程技术不断融合的时代,理解并应用好模板方法模式,无疑是我们每位程序员“喝口茶”就能掌握的一项重要技能。泡一壶好茶,编一段好码,两者皆是匠心独具的艺术,都在追求着简单中的不凡,平凡中的卓越。