C# 设计模式之模板方法模式

总目录


前言

在日常的工作中,有时候我们做PPT,做合同,做简历,如果我们自己从头去写这些文档,不免有些太过耗时耗力;大多时候都是去找相关的PPT模板,合同模板,简历模板,拿过来直接用。为什么可以使用模板,因此这些资料大部分的信息和信息框架都是一致的,我们只需要将自己差异化的内容填写进去就可以,模板的作用就是将公有的格式,框架,信息提取出来都做好,使用模板的人只需填写个人差异化的信息即可。模板方法设计模式就是按照这个思想来设计代码的,在软件构建过程中,对于某一项任务,如果它常常有稳定的整体操作结构,但各个子步骤内却有很多改变的需求,这个时候就可以应用模板方法模式。


1 基础介绍

  1. 定义:定义一个操作中的算法骨架,将某些步骤延迟到子类中实现。
  2. 定义解释:在一个抽象类中定义一个操作中的算法骨架(对应于生活中的大家下载的模板),而将一些步骤延迟到子类中去实现(对应于我们根据自己的情况向模板填充内容)。模板方法使得子类可以不改变一个算法的结构前提下,重新定义算法的某些特定步骤,模板方法模式把不变行为搬到基类中,从而去除了子类中的重复代码。
  3. 模板方法模式中的角色:
    • 抽象类角色(AbstractClass):定义一个模板方法(TemplateMethod),在该方法中包含着一个算法的骨架,具体的算法步骤是PrimitiveOperation1方法和PrimitiveOperation2方法,该抽象类的子类将重定义PrimitiveOperation1和PrimitiveOperation2操作。
    • 具体类角色(ConcreteClass):实现PrimitiveOperation1方法和PrimitiveOperation2方法以完成算法中与特定子类(Client)相关的内容。
  4. 模板方法模式在抽象类中定义了算法的实现步骤,将这些步骤的实现延迟到具体子类中去实现,从而使所有子类复用了父类的代码,所以模板方法模式是基于继承的一种实现代码复用的技术。

2 使用场景

适用于 某个功能需要多个步骤实现,整体的实现步骤是不变的,只是具体的某些子步骤会存在差异的情况,这样就可以将实现步骤提取到基类,具体的实现交给实现类去完成。

3 实现方式

在C#中,使用模板方法的关键是要定义一个抽象类AbstractClass,它包含了一个模板方法TemplateMethod,该方法包含所有的算法流程,但某些步骤需要由子类来具体实现。因此,在抽象类中,通常会定义一些虚方法,用于在子类中具体实现算法:

csharp 复制代码
    public abstract class AbstractClass
    {
        public void TemplateMethod()
        {
            // 模板方法,定义算法骨架  
            //步骤1
            PrimitiveOperation1();
            //步骤2
            PrimitiveOperation2();
            //步骤3
            PrimitiveOperation3();
            // ...  
        }

        // 步骤1(原始操作1):抽象方法,由子类具体实现
        public abstract void PrimitiveOperation1(); 

        //步骤2(原始操作2):抽象方法,由子类具体实现
        public abstract void PrimitiveOperation2();

        //步骤3(原始操作2):抽象方法,由子类具体实现
        public virtual void PrimitiveOperation3()
        {
            //在这里这里写上基类会有的基本操作
            Console.WriteLine("AbstractClass:base Operation3");
            //也可以什么都不写,默认实现为空,交由子类重写
        }

    }

在抽象类中,定义了一个模板方法TemplateMethod(),其中具体的算法流程已经定义好了,但某些步骤则需要由子类来具体实现,因此,在抽象类中,对于某些需要具体实现的步骤,我们使用抽象方法进行声明,在子类中需要对这些抽象方法进行具体实现;而对于某些步骤,它们的实现可以在基类中进行默认实现,因此,我们可以使用虚方法进行声明,在子类中也可以选择覆盖这些虚方法。

然后,创建两个继承自AbstractClass的具体类,实现这些抽象方法:

csharp 复制代码
    public class ConcreteClassA : AbstractClass
    {
        public override void PrimitiveOperation1()
        {
            Console.WriteLine("ConcreteClassA: PrimitiveOperation1");
        }

        public override void PrimitiveOperation2()
        {
            Console.WriteLine("ConcreteClassA: PrimitiveOperation2");
        }
    }

    public class ConcreteClassB : AbstractClass
    {
        public override void PrimitiveOperation1()
        {
            Console.WriteLine("ConcreteClassB: PrimitiveOperation1");
        }

        public override void PrimitiveOperation2()
        {
            Console.WriteLine("ConcreteClassB: PrimitiveOperation2");
        }
		
		// 这里基于virtual方法重写,并加上自有的代码
        public override void PrimitiveOperation3()
        {
            base.PrimitiveOperation3();
            Console.WriteLine("ConcreteClassB: PrimitiveOperation3");
        }
    }

客户端调用:

csharp 复制代码
        static void Main(string[] args)
        {
            AbstractClass abstractClass = new ConcreteClassA();
            
            // 调用TemplateMethod方法,
            //该方法会依次调用ConcreteClassA实现类中的各个实现方法
            abstractClass.TemplateMethod();
 
            abstractClass = new ConcreteClassB(); 
            
            // 再次调用TemplateMethod方法,这次会使用ConcreteClassB的实现。
            abstractClass.TemplateMethod();

            Console.ReadKey();

        }

4 优缺点分析

  • 优点

    • 使用模板方法可以使得代码的重复度降低,代码得到复用
    • 能够灵活应对子步骤的变化,符合开放-封闭原则
  • 缺点

    • 由于引入了一个抽象类,使程序代码变得复杂化

结语

希望以上内容可以帮助到大家,如文中有不对之处,还请批评指正。


参考资料:
C#设计模式14------模板方法的写法
C#设计模式之十三模板方法模式(Template Method Pattern)【行为型】
C#设计模式(14)------模板方法模式(Template Method)
使用 C# 实现23种常见的设计模式

相关推荐
AI人工智能+电脑小能手5 小时前
大白话说Java设计模式-08-建造者模式(业务实战篇)
java·设计模式·建造者模式·架构设计·对象构建
唐青枫8 小时前
别再手写 args[0]:C#.NET CommandLineParser 命令行工具实战详解
c#·.net
AustinXu8 小时前
从 Claude Code 到 Claude Tag,Harness Engineering 走到了组织这一层
设计模式·团队管理
剧中有戏8 小时前
单例模式从入门到精通:一个数据库连接池的完整剖析
设计模式
胡萝卜术8 小时前
编译期与运行期的双重防线:从 TypeScript 类型之争到 LLM 输出的自动化择优
前端·设计模式·面试
货拉拉技术8 小时前
重塑 Agent 度量衡:基于 LLM-as-a-Judge 的离线评估体系与实践
算法·设计模式
LccKyI8 小时前
C#学习day06(方法/函数及其关键字,附思维导图)
经验分享·学习·c#
KhalilRuan9 小时前
设计模式小记
设计模式
.Peter9 小时前
.NET/WPF 程序在部分 Windows 电脑无法保存用户环境变量:使用 DPAPI 实现安全兼容
windows·信息安全·c#·.net·wpf·环境变量·dpapi
卡牌RWA研究院9 小时前
Relique:一张精品卡牌如何从收藏品变成可交易的链上资产?
设计模式·金融·区块链·创业创新