• 设计模式 22 模板方法模式


    设计模式 22

    • 创建型模式(5):工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式
    • 结构型模式(7):适配器模式、桥接模式、组合模式、装饰者模式、外观模式、享元模式、代理模式
    • 行为型模式(11):责任链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法模式、访问者模式

    模板方法模式(Template Method Pattern)

    1 定义

    模板方法模式通过在基类中定义一个模板方法,该方法封装了一个算法的固定步骤,然后允许子类实现或重写这些步骤。这样,子类可以定制算法的具体行为,而无需改变算法的整体结构。

    2 结构

    模板方法模式包含以下角色:

    • 抽象类(AbstractClass): 定义模板方法和算法的骨架。模板方法按照固定的步骤调用抽象方法或具体方法。
    • 具体类(ConcreteClass): 继承自抽象类,实现或重写抽象方法,定义算法的具体步骤。

    UML 类图

    +---------------------------+     
    |  AbstractClass            |     
    +---------------------------+     
    | + TemplateMethod(): void  |     
    | + Step1(): void           |     
    | + Step2(): void           |     
    | - Step3(): void           |     
    +---------------------------+     
            ^     
            |     
    +-------------------+     
    |  ConcreteClass    |     
    +-------------------+     
    | - Step3(): void   |     
    +-------------------+
    

    3 示例代码

    假设我们要制作一杯饮料,制作的过程包括煮水、冲泡、倒入杯中、添加配料等步骤。咖啡和茶是两种不同的饮料,它们在制作过程中的步骤基本相同,但在某些步骤上有所不同。我们可以使用模板方法模式来实现这个场景。

    抽象类

    // 抽象类 - 饮料制作过程
    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();
    }
    

    具体类

    // 具体类 - 茶
    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");
        }
    }
    

    客户端代码

    class Program
    {
        static void Main(string[] args)
        {
            Beverage tea = new Tea();
            tea.PrepareRecipe();  // 制作茶
    
            Console.WriteLine();
    
            Beverage coffee = new Coffee();
            coffee.PrepareRecipe();  // 制作咖啡
        }
    }
    

    运行结果

    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 总结

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

  • 相关阅读:
    vue相关面试题:MVC,MVP,MVVP三种设计模式的区别
    二维码智慧门牌管理系统:提升城市管理效率与便捷性
    汇率兑换查询易语言代码
    Autojs微信研究:微信自动发送信息机器人最终成品(有效果演示)
    axios请求的问题
    [无线通信基础-13]:图解移动通信技术与应用发展-1-概述
    技术前沿|Spark 3.3.0 中 DS V2 Push-down 的重构与新特性
    volatile关键字
    周记之反思
    Linux下PC与开发板进行数据通讯的三种方式
  • 原文地址:https://blog.csdn.net/szy13323042191/article/details/142096591