设计模式 22
- 创建型模式(5):工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式
- 结构型模式(7):适配器模式、桥接模式、组合模式、装饰者模式、外观模式、享元模式、代理模式
- 行为型模式(11):责任链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法模式、访问者模式
文章目录
- [设计模式 22](#设计模式 22)
- 
- [模板方法模式(Template Method Pattern)](#模板方法模式(Template Method Pattern))
- 
- [1 定义](#1 定义)
- [2 结构](#2 结构)
- [3 示例代码](#3 示例代码)
- [4 特点](#4 特点)
- [5 适用场景](#5 适用场景)
- [6 总结](#6 总结)
 
 
模板方法模式(Template Method Pattern)
1 定义
模板方法模式通过在基类中定义一个模板方法,该方法封装了一个算法的固定步骤,然后允许子类实现或重写这些步骤。这样,子类可以定制算法的具体行为,而无需改变算法的整体结构。
2 结构
模板方法模式包含以下角色:
- 抽象类(AbstractClass): 定义模板方法和算法的骨架。模板方法按照固定的步骤调用抽象方法或具体方法。
- 具体类(ConcreteClass): 继承自抽象类,实现或重写抽象方法,定义算法的具体步骤。
UML 类图
            
            
              scss
              
              
            
          
          +---------------------------+     
|  AbstractClass            |     
+---------------------------+     
| + TemplateMethod(): void  |     
| + Step1(): void           |     
| + Step2(): void           |     
| - Step3(): void           |     
+---------------------------+     
        ^     
        |     
+-------------------+     
|  ConcreteClass    |     
+-------------------+     
| - Step3(): void   |     
+-------------------+3 示例代码
假设我们要制作一杯饮料,制作的过程包括煮水、冲泡、倒入杯中、添加配料等步骤。咖啡和茶是两种不同的饮料,它们在制作过程中的步骤基本相同,但在某些步骤上有所不同。我们可以使用模板方法模式来实现这个场景。
抽象类
            
            
              csharp
              
              
            
          
          // 抽象类 - 饮料制作过程
public abstract class Beverage
{
    // 模板方法
    public void PrepareRecipe()
    {
        BoilWater();
        Brew();
        PourInCup();
        AddCondiments();
    }
    // 具体方法 - 煮水
    private void BoilWater()
    {
        Console.WriteLine("Boiling water");
    }
    // 抽象方法 - 冲泡
    protected abstract void Brew();
    // 具体方法 - 倒入杯中
    private void PourInCup()
    {
        Console.WriteLine("Pouring into cup");
    }
    // 抽象方法 - 添加配料
    protected abstract void AddCondiments();
}具体类
            
            
              csharp
              
              
            
          
          // 具体类 - 茶
public class Tea : Beverage
{
    protected override void Brew()
    {
        Console.WriteLine("Steeping the tea");
    }
    protected override void AddCondiments()
    {
        Console.WriteLine("Adding lemon");
    }
}
// 具体类 - 咖啡
public class Coffee : Beverage
{
    protected override void Brew()
    {
        Console.WriteLine("Dripping coffee through filter");
    }
    protected override void AddCondiments()
    {
        Console.WriteLine("Adding sugar and milk");
    }
}客户端代码
            
            
              csharp
              
              
            
          
          class Program
{
    static void Main(string[] args)
    {
        Beverage tea = new Tea();
        tea.PrepareRecipe();  // 制作茶
        Console.WriteLine();
        Beverage coffee = new Coffee();
        coffee.PrepareRecipe();  // 制作咖啡
    }
}运行结果
            
            
              plaintext
              
              
            
          
          Boiling water
Steeping the tea
Pouring into cup
Adding lemon
Boiling water
Dripping coffee through filter
Pouring into cup
Adding sugar and milk在这个例子中,Beverage 是抽象类,定义了一个模板方法 PrepareRecipe(),它包含了制作饮料的固定步骤。这些步骤中,有些是具体实现的(如 BoilWater() 和 PourInCup()),而有些是抽象方法,由子类 Tea 和 Coffee 来实现(如 Brew() 和 AddCondiments())。客户端代码可以使用不同的具体类来制作不同的饮料,而不需要关心具体的实现细节。
4 特点
- 
优点: - 
代码复用: 将通用的算法步骤封装到基类中,子类只需要实现差异化的部分,减少了重复代码。 
- 
扩展性强: 子类可以根据需要重写或扩展某些步骤,增加算法的灵活性。 
- 
控制算法结构: 父类定义了算法的骨架,确保了算法的整体结构不被子类破坏。 
 
- 
- 
缺点: - 
增加代码复杂性: 由于引入了继承关系和抽象方法,可能会使代码结构变得复杂。 
- 
对子类的依赖: 父类依赖子类来实现某些步骤,可能导致子类必须实现某些方法,即使这些方法在特定情况下并不需要。 
 
- 
5 适用场景
- 多个类有相似的操作步骤: 当多个类的操作步骤大致相同时,可以使用模板方法模式将相同的部分提取到抽象类中。
- 算法需要多个步骤: 当算法需要分解为多个步骤,并且这些步骤中有些是固定的,有些是可变的,可以使用模板方法模式。
- 控制算法的流程: 当需要确保算法的某些步骤必须按照一定的顺序执行时,可以使用模板方法模式。
6 总结
模板方法模式通过将通用的算法步骤封装到抽象类中,允许子类重写或扩展特定的步骤,实现了算法的复用和扩展。它确保了算法的整体结构不被破坏,同时为子类提供了灵活性。在多个类具有相似的操作步骤时,模板方法模式是一种非常有效的设计模式。