模板方法(Template Method)是一种设计模式,它定义了一个操作中的算法的骨架,将某些步骤推迟到子类中实现,从而使得子类可以在不改变算法骨架的情况下重新定义算法的某些步骤。
作用:
使用模板方法可以使得代码的重复度降低,同时也能够避免由于算法中某个特定步骤的改变导致整体算法需要改变的情况。此外,模板方法也使得维护和扩展代码变得更加容易。
怎么做:
在C#中,可以通过抽象类和虚方法来实现模板方法。具体的做法是,定义一个抽象类,声明大致的算法流程,并将其中某些步骤声明为虚方法,待子类继承该抽象类后,根据需要实现其虚方法。这样,就可以通过调用抽象类中的算法流程,由子类来具体实现算法中的某些步骤,从而得出结果。
何时用:
模板方法常用于以下场景:
1.在多个类中有相同的方法,但具体的实现细节有所不同。
2.需要在代码中使用一种算法,但是该算法中某些步骤需要根据具体情况进行不同的实现。
3.需要保证所有使用该算法的地方都能得到相同的结果。
4.需要把具体的实现过程从算法中分离开来,使得算法更容易扩展和维护。
5.需要让子类只能实现算法中的某一部分,而不能改变整个算法的结构。
如何实现:
在C#中,使用模板方法的关键是要定义一个抽象类,包含所有的算法流程,但某些步骤需要由子类来具体实现。因此,在抽象类中,通常会定义一些虚方法,用于在子类中具体实现算法。抽象类的代码示例:
代码语言:javascript复制//抽象类
public abstract class AbstractClass
{
//模板方法,定义算法骨架
public void TemplateMethod()
{
//步骤1
Step1();
//步骤2
Step2();
//步骤3
Step3();
}
//步骤1(抽象方法,由子类具体实现)
public abstract void Step1();
//步骤2(虚方法,子类可以覆盖,默认实现为空)
public virtual void Step2()
{
//默认实现为空
}
//步骤3(抽象方法,由子类具体实现)
public abstract void Step3();
}
在抽象类中,定义了一个模板方法TemplateMethod(),其中具体的算法流程已经定义好了,但某些步骤则需要由子类来具体实现,因此,在抽象类中,对于某些需要具体实现的步骤,我们使用抽象方法进行声明,在子类中需要对这些抽象方法进行具体实现;而对于某些步骤,它们的实现可以在基类中进行默认实现,因此,我们可以使用虚方法进行声明,在子类中也可以选择覆盖这些虚方法。
下面是一个使用模板方法的示例:
代码语言:javascript复制//具体类1
public class ConcreteClassA : AbstractClass
{
public override void Step1()
{
Console.WriteLine("ConcreteClassA:Step1");
}
public override void Step3()
{
Console.WriteLine("ConcreteClassA:Step3");
}
}
//具体类2
public class ConcreteClassB : AbstractClass
{
public override void Step1()
{
Console.WriteLine("ConcreteClassB:Step1");
}
public override void Step2()
{
Console.WriteLine("ConcreteClassB:Step2");
}
public override void Step3()
{
Console.WriteLine("ConcreteClassB:Step3");
}
}
//客户端调用
class Client
{
static void Main(string[] args)
{
AbstractClass ac1 = new ConcreteClassA();
ac1.TemplateMethod();
AbstractClass ac2 = new ConcreteClassB();
ac2.TemplateMethod();
}
}
在这个示例中,我们定义了两个具体类——ConcreteClassA和ConcreteClassB,它们都继承了抽象类AbstractClass,并根据需要实现了其中的虚方法。
在主函数中,我们实例化了这两个具体类,并分别调用它们的TemplateMethod()方法,从而得到了两个具体类的实例化对象。这些对象都实现了同样的模板方法(算法流程),但由于其中某些步骤使用了不同的实现方法,输出结果也不同:
``` ConcreteClassA:Step1 ConcreteClassA:Step2 ConcreteClassA:Step3
ConcreteClassB:Step1 ConcreteClassB:Step2 ConcreteClassB:Step3 ```