总目录
前言
在日常的工作中,有时候我们做PPT,做合同,做简历,如果我们自己从头去写这些文档,不免有些太过耗时耗力;大多时候都是去找相关的PPT模板,合同模板,简历模板,拿过来直接用。为什么可以使用模板,因此这些资料大部分的信息和信息框架都是一致的,我们只需要将自己差异化的内容填写进去就可以,模板的作用就是将公有的格式,框架,信息提取出来都做好,使用模板的人只需填写个人差异化的信息即可。模板方法设计模式就是按照这个思想来设计代码的,在软件构建过程中,对于某一项任务,如果它常常有稳定的整体操作结构,但各个子步骤内却有很多改变的需求,这个时候就可以应用模板方法模式。
1 基础介绍
- 定义:定义一个操作中的算法骨架,将某些步骤延迟到子类中实现。
- 定义解释:在一个抽象类中定义一个操作中的算法骨架(对应于生活中的大家下载的模板),而将一些步骤延迟到子类中去实现(对应于我们根据自己的情况向模板填充内容)。模板方法使得子类可以不改变一个算法的结构前提下,重新定义算法的某些特定步骤,模板方法模式把不变行为搬到基类中,从而去除了子类中的重复代码。
- 模板方法模式中的角色:
- 抽象类角色(AbstractClass):定义一个模板方法(TemplateMethod),在该方法中包含着一个算法的骨架,具体的算法步骤是PrimitiveOperation1方法和PrimitiveOperation2方法,该抽象类的子类将重定义PrimitiveOperation1和PrimitiveOperation2操作。
- 具体类角色(ConcreteClass):实现PrimitiveOperation1方法和PrimitiveOperation2方法以完成算法中与特定子类(Client)相关的内容。
- 模板方法模式在抽象类中定义了算法的实现步骤,将这些步骤的实现延迟到具体子类中去实现,从而使所有子类复用了父类的代码,所以模板方法模式是基于继承的一种实现代码复用的技术。
2 使用场景
适用于 某个功能需要多个步骤实现,整体的实现步骤是不变的,只是具体的某些子步骤会存在差异的情况,这样就可以将实现步骤提取到基类,具体的实现交给实现类去完成。
3 实现方式
在C#中,使用模板方法的关键是要定义一个抽象类AbstractClass,它包含了一个模板方法TemplateMethod,该方法包含所有的算法流程,但某些步骤需要由子类来具体实现。因此,在抽象类中,通常会定义一些虚方法,用于在子类中具体实现算法:
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的具体类,实现这些抽象方法:
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");
}
}
客户端调用:
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种常见的设计模式