“四人帮”23种设计模式可分为三大类:创建型,结构型,行为型。每种模式中都有一个最常用的模式,例如,创建型中最常用的是工厂方法模式,结构型模式中最常用的是适配器模式,行为型模式中最常用的是模板方法模式,本节重点讲解模板方法模式。
模板方法模式是最简单的设计模式,起这样的一个名字听起来可能感觉很专业,其实只要大家写过面向对象,就一定熟悉这个模式。说的更简单一点,只要抽象基类中定义了一个受保护的Abastract方法,并提供一个公开的访问接口(供子类访问),然后让子类去重写这个抽象方法,就是模板方法模式最常见的应用。
为什么要用到模板方法模式呢?我们知道,通常写代码的时候,通常一个方法里面会包含几个子方法,但是其中一个方法,在基类中并不知道它具体有什么用途,只能由子类去决定具体要做什么事情,但是在基类中,我们必须按照事情的先后顺序执行(事件1->事件2->事件3->事件4),才能符合正常流程,如下图:
要执行的方法如下:
1 /// <summary>
2 /// schedule template
3 /// </summary>
4 abstract class Schedule
5 {
6 public void Execute()
7 {
8 ExecuteThings1();
9 ExecuteThings2();
10 ExecuteThings3();
11 ExecuteThings4();
12 }
13
14 private void ExecuteThings1()
15 {
16 //execute the concrete thing for Things1
17 //such as: Print something.
18 }
19
20 private void ExecuteThings3()
21 {
22 //execute the concrete thing for Things3
23 //such as : access the database
24 }
25
26 private void ExecuteThings4()
27 {
28 //execute the concrete thing for Things4
29 //write something to the EventViewer
30 }
31
32 private void ExecuteThings2()
33 {
34 //do nothing
35 }
36 }
View Code
可是ExecuteThings2()方法我们不知道要做什么,这时候怎么办呢,直接写成吧,等于写了一个空方法,啥也都执行,并且当子类要继续时也不能根据具体执行什么东东来重写这个方法,这个方法并不能在动态运行时有多种表现,不满足多态的特点。
1 private void ExecuteThings2()
2 {
3 //do nothing
4 }
View Code
为了达到子类按需定制,就是大家常说的“钩子”效果,可以首先将方法申明为virtual/abstract,以便子类重写,因为这个方法是一个抽象方法(空方法,什么也不做,等同于C++中的纯虚函数),所以将该方法申明为abstract抽象方法,为了便于子类重写,而不被外界访问,我们使用保护修饰符protected,达到钩子效果,代码如下:
1 /// <summary>
2 /// schedule template
3 /// </summary>
4 abstract class Schedule
5 {
6 public void Execute()
7 {
8 ExecuteThings1();
9 ExecuteThings2();
10 ExecuteThings3();
11 ExecuteThings4();
12 }
13
14 private void ExecuteThings1()
15 {
16 //execute the concrete thing for Things1
17 //such as: Print something.
18 }
19
20 private void ExecuteThings3()
21 {
22 //execute the concrete thing for Things3
23 //such as : access the database
24 }
25
26 private void ExecuteThings4()
27 {
28 //execute the concrete thing for Things4
29 //write something to the EventViewer
30 }
31
32 private void ExecuteThings2()
33 {
34 //call the hook
35 DoExecuteThings2();
36 }
37
38 /// <summary>
39 /// hook method, the sub inherited class will implement the details.
40 /// </summary>
41 protected abstract void DoExecuteThings2();
42
43 }
View Code
于是,子类可以按需重写他自己想要执行的事情。
1 class GroupASchedule : Schedule
2 {
3 protected override void DoExecuteThings2()
4 {
5 Console.WriteLine("{0} -> we will execute my plan for GroupA!", this.GetType().Name);
6 }
7 }
8
9 class GroupBSchedule : Schedule
10 {
11 protected override void DoExecuteThings2()
12 {
13 Console.WriteLine("{0} -> we will execute my plan for GroupB!", this.GetType().Name);
14 }
15 }
View Code
从而,实现了想做的具体事情2。
示例代码: YearlyArrangement.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Template
{
abstract class YearlyArrangement
{
protected virtual void Work()
{
Console.WriteLine("Most of the time, we are working!");
}
/// <summary>
/// hook method
/// sub-class should override this method
/// </summary>
protected abstract void MakeEntertainmentEveryYear();
protected virtual void AwardPrize()
{
Console.WriteLine("At the end of each year, the company holds an award-prize ceremony!");
}
protected virtual void AttendAnnualMeeting()
{
Console.WriteLine("At the end of each year, the company holds an annual meeting!");
}
public void MakePlan()
{
Console.WriteLine("Year: {0}", this.GetType().Name.Replace("Year", string.Empty));
Work();
MakeEntertainmentEveryYear();
AwardPrize();
AttendAnnualMeeting();
Console.WriteLine();
}
}
}
Year2013.cs:
class Year2013 : YearlyArrangement
{
protected override void MakeEntertainmentEveryYear()
{
Console.WriteLine("Travelling to America!");
}
}
Year2014.cs:
class Year2014 : YearlyArrangement
{
protected override void MakeEntertainmentEveryYear()
{
Console.WriteLine("Travelling to Paris!");
}
}
Year2015.cs:
class Year2015 : YearlyArrangement
{
protected override void MakeEntertainmentEveryYear()
{
Console.WriteLine("Go to lenovo for learning!");
}
}
主函数Program.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Template
{
class Program
{
static void Main(string[] args)
{
Test();
}
static void Test()
{
YearlyArrangement year = new Year2013();
year.MakePlan();
year = new Year2014();
year.MakePlan();
year = new Year2015();
year.MakePlan();
Console.ReadKey();
}
}
}
运行效果:
源代码下载: https://capps.codeplex.com/releases/view/107754
由于水平有限,难免有描述不够准确之处,欢迎大家指正。
原文链接: https://www.cnblogs.com/Bowl2008/archive/2013/06/08/template_method_design_patterns.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/91675
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!