模板方法模式(Template Method Pattern)

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介: 模板方法模式是一种行为型设计模式,定义一个操作中的算法骨架,将某些步骤的实现延迟到子类。子类可以在不改变算法结构的情况下重新定义算法的某些步骤。适用于多个类有相似操作流程且部分步骤需要定制的场景。优点包括高复用性、扩展性强和清晰明确;缺点是灵活性降低和可能引入性能开销。示例包括文件解析和策略模式的对比。

模板方法模式(Template Method Pattern)详解

1. 定义

模板方法模式是一种行为型设计模式,定义一个操作中的算法骨架,将某些步骤的实现延迟到子类。通过模板方法,子类可以在不改变算法结构的情况下重新定义算法的某些步骤。

通俗解释:

模板方法就像烹饪中的食谱,它定义了做菜的步骤(算法骨架),而每道菜的具体细节(比如调味方式)由厨师(子类)决定。这样既保证了流程的一致性,又允许定制化。


2. 使用场景

使用场景 描述
算法框架一致,细节可变 比如不同类型的文件解析:整体流程相同,但具体解析逻辑因文件类型不同而不同。
避免重复代码 公共逻辑上移到父类,实现代码复用,具体逻辑留给子类实现。
确保算法框架不被修改 算法骨架在父类中定义,不允许被改变,而只开放局部步骤供子类扩展。

3. 模板方法模式的优缺点

特性 模板方法模式 策略模式
优点 复用性高:提取通用逻辑,避免重复代码。
扩展性强:子类只需实现定制化步骤。
清晰明确:明确了算法的执行顺序,逻辑更清楚。
灵活性高:可以在运行时动态替换算法或行为。
扩展性强:通过新增策略类来扩展新的算法或行为,无需修改原有代码。
遵循开闭原则:对扩展开放,对修改封闭。
缺点 灵活性降低:父类定义的算法框架限制了子类的自由度。
继承问题:容易导致子类层次结构过于复杂。
违反开闭原则:算法框架一旦定义,修改困难。
可能的性能开销:在某些情况下,策略模式可能引入额外的性能开销,因为需要在运行时决定使用哪个策略。
客户端代码复杂性:客户端可能需要了解所有策略的细节,以便在适当的时机选择和使用它们。

4. 模板方法模式的组成

  1. 抽象类
    定义算法的骨架(模板方法)和必要的抽象方法。
  2. 具体子类
    实现抽象类中的具体步骤,定制行为。
  3. 模板方法
    在抽象类中定义,通常是 final 的,不允许子类修改。

5. 示例:文件解析

示例描述:

不同类型的文件(比如 JSON 和 XML)解析逻辑大致相同:

  1. 打开文件。
  2. 读取内容。
  3. 解析数据。
  4. 关闭文件。

其中,解析数据的细节因文件类型不同而不同。


C++ 示例

#include <iostream>
#include <string>
using namespace std;

// 抽象类:文件解析器
class FileParser {
public:
   // 模板方法,定义解析流程
   void parseFile(const string& fileName) {
       openFile(fileName);
       readFile();
       parseData();  // 留给子类实现
       closeFile();
   }

   virtual ~FileParser() = default;

protected:
   void openFile(const string& fileName) {
       cout << "Opening file: " << fileName << endl;
   }

   void readFile() {
       cout << "Reading file content..." << endl;
   }

   virtual void parseData() = 0;  // 抽象方法,子类实现

   void closeFile() {
       cout << "Closing file." << endl;
   }
};

// 具体子类:JSON文件解析器
class JSONParser : public FileParser {
protected:
   void parseData() override {
       cout << "Parsing JSON data." << endl;
   }
};

// 具体子类:XML文件解析器
class XMLParser : public FileParser {
protected:
   void parseData() override {
       cout << "Parsing XML data." << endl;
   }
};

// 客户端代码
int main() {
   FileParser* parser = new JSONParser();
   parser->parseFile("data.json");
   delete parser;

   parser = new XMLParser();
   parser->parseFile("data.xml");
   delete parser;

   return 0;
}


C# 示例

using System;

// 抽象类:文件解析器
public abstract class FileParser {
   // 模板方法
   public void ParseFile(string fileName) {
       OpenFile(fileName);
       ReadFile();
       ParseData(); // 留给子类实现
       CloseFile();
   }

   protected void OpenFile(string fileName) {
       Console.WriteLine($"Opening file: {fileName}");
   }

   protected void ReadFile() {
       Console.WriteLine("Reading file content...");
   }

   protected abstract void ParseData(); // 抽象方法

   protected void CloseFile() {
       Console.WriteLine("Closing file.");
   }
}

// 具体子类:JSON文件解析器
public class JSONParser : FileParser {
   protected override void ParseData() {
       Console.WriteLine("Parsing JSON data.");
   }
}

// 具体子类:XML文件解析器
public class XMLParser : FileParser {
   protected override void ParseData() {
       Console.WriteLine("Parsing XML data.");
   }
}

// 客户端代码
class Program {
   static void Main() {
       FileParser parser = new JSONParser();
       parser.ParseFile("data.json");

       parser = new XMLParser();
       parser.ParseFile("data.xml");
   }
}


模板方法模式的类图

6. 模板方法模式的扩展

钩子方法(Hook Method)

模板方法模式中可以包含钩子方法,子类可以通过覆盖钩子方法来影响模板方法的行为,但不是必须实现的。这种方法进一步增强了模式的灵活性。


7. 模板方法模式与其他模式对比

特性 模板方法模式 策略模式
核心作用 固定算法流程,允许部分步骤定制 动态替换算法或行为
子类角色 扩展部分算法步骤 提供具体算法实现
抽象层次 抽象类和子类 接口和实现类
场景适用 算法逻辑固定但有定制需求 需要灵活切换算法或行为

模板方法模式总结

  1. 适用范围:当多个类具有相似的操作流程,且部分步骤需要定制时,使用模板方法模式非常合适。
  2. 设计哲学:使用“模板”将不变的部分抽象出来,同时开放定制点以支持扩展。
  3. 注意事项:避免过多的抽象和继承层次,防止代码复杂化。
目录
相关文章
|
设计模式 算法
设计模式9 - 模板方法模式【Template Method Pattern】
设计模式9 - 模板方法模式【Template Method Pattern】
43 0
|
存储 算法 Java
行为型模式 - 模板模式(Template Pattern)
行为型模式 - 模板模式(Template Pattern)
|
Java
装饰器模式(Decorator Pattern)
装饰器模式(Decorator Pattern)
102 0
装饰器模式(Decorator Pattern)
|
Java Spring
Spring源码(二-2)-lookup-method、replaced-method标签
lookup-method 通常称为获取器注入,spring in action 中对它的描述是,一种特殊的方法注入,它是把一个方法声明为返回某种类型的 bean,而实际要返回的 bean 是在配置文件里面配置的。
584 1
|
设计模式 算法 Java
模板方法设计模式(Template Pattern)(下)
模板方法设计模式(Template Pattern)(下)
127 0
模板方法设计模式(Template Pattern)(下)
|
设计模式 算法 Java
模板方法设计模式(Template Pattern)(上)
模板方法设计模式(Template Pattern)(上)
134 0
模板方法设计模式(Template Pattern)(上)
|
设计模式 JSON 算法
【愚公系列】2021年12月 二十三种设计模式(二十二)-模板方法模式(Template Method Pattern)
【愚公系列】2021年12月 二十三种设计模式(二十二)-模板方法模式(Template Method Pattern)
126 0
【愚公系列】2021年12月 二十三种设计模式(二十二)-模板方法模式(Template Method Pattern)
|
算法 C# Java
使用C# (.NET Core) 实现模板方法模式 (Template Method Pattern)
本文的概念内容来自深入浅出设计模式一书. 项目需求 有一家咖啡店, 供应咖啡和茶, 它们的工序如下: 咖啡: 茶: 可以看到咖啡和茶的制作工序是差不多的, 都是有4步, 其中有两步它们两个是一样的, 另外两步虽然具体内容不一样, 但是都做做的同一类工作.
1378 0

热门文章

最新文章