设计模式 22 模板方法模式

设计模式 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()),而有些是抽象方法,由子类 TeaCoffee 来实现(如 Brew()AddCondiments())。客户端代码可以使用不同的具体类来制作不同的饮料,而不需要关心具体的实现细节。

4 特点

  • 优点:

    • 代码复用: 将通用的算法步骤封装到基类中,子类只需要实现差异化的部分,减少了重复代码。

    • 扩展性强: 子类可以根据需要重写或扩展某些步骤,增加算法的灵活性。

    • 控制算法结构: 父类定义了算法的骨架,确保了算法的整体结构不被子类破坏。

  • 缺点:

    • 增加代码复杂性: 由于引入了继承关系和抽象方法,可能会使代码结构变得复杂。

    • 对子类的依赖: 父类依赖子类来实现某些步骤,可能导致子类必须实现某些方法,即使这些方法在特定情况下并不需要。

5 适用场景

  • 多个类有相似的操作步骤: 当多个类的操作步骤大致相同时,可以使用模板方法模式将相同的部分提取到抽象类中。
  • 算法需要多个步骤: 当算法需要分解为多个步骤,并且这些步骤中有些是固定的,有些是可变的,可以使用模板方法模式。
  • 控制算法的流程: 当需要确保算法的某些步骤必须按照一定的顺序执行时,可以使用模板方法模式。

6 总结

模板方法模式通过将通用的算法步骤封装到抽象类中,允许子类重写或扩展特定的步骤,实现了算法的复用和扩展。它确保了算法的整体结构不被破坏,同时为子类提供了灵活性。在多个类具有相似的操作步骤时,模板方法模式是一种非常有效的设计模式。

相关推荐
思忖小下4 小时前
梳理你的思路(从OOP到架构设计)_简介设计模式
设计模式·架构·eit
liyinuo20176 小时前
嵌入式(单片机方向)面试题总结
嵌入式硬件·设计模式·面试·设计规范
aaasssdddd968 小时前
C++的封装(十四):《设计模式》这本书
数据结构·c++·设计模式
T1an-19 小时前
设计模式之【观察者模式】
观察者模式·设计模式
思忖小下10 小时前
梳理你的思路(从OOP到架构设计)_设计模式Factory Method模式
设计模式·工厂方法模式·eit
霁月风11 小时前
设计模式——工厂方法模式
c++·设计模式·工厂方法模式
发飙的蜗牛'13 小时前
23种设计模式
android·java·设计模式
NorthCastle1 天前
设计模式-创建型模式-简单工厂模式详解
设计模式·简单工厂模式
越甲八千1 天前
重拾设计模式-外观模式和适配器模式的异同
设计模式·适配器模式·外观模式
越甲八千1 天前
重拾设计模式--适配器模式
设计模式·适配器模式