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

思考并回答以下问题:

模板方法模式介绍

提到模板我们经常会想到简历模板/PPT模板等,以简历模板为例,不同的人可以使用一样的简历模板,在填充内容时根据自己的名字/工作经历等填写自己的内容,从而形成不同的简历。在OO中模板方法模式和现实中的模板十分相似,首先要有一个封装了不可变部分的抽象类(简历的大致结构,都有姓名、性别、年龄、工作经历等),然后将可变部分延迟到子类中(不同人的简历内容不同,这些不同的内容放在子类中实现),模板方法就是多态的一种实现。抽象类中模板方法不仅仅可以定义内容的,也可以定义执行的顺序。

以游戏厅打游戏为例,我们去游戏厅不管玩什么游戏都可以归结为四步:先投币,游戏初始化,玩游戏,游戏结束。这四步的顺序是不变的,其中第一步是不能改变的,无论我们玩什么游戏都要先投币。我们在代码中来理解模板方法模式的用法。

抽象游戏类和具体游戏类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/// <summary>
/// 抽象游戏类
/// </summary>
public abstract class Game
{
// 每款游戏都要投币,子类不能重写
public void InsertCoins()
{
Console.WriteLine("往游戏机里投币...");
}
public abstract void InitGame();
public abstract void StartGame();
public abstract void EndGame();

// Play是模板方法,定义了子类执行的步骤
public void Play()
{
// 投币
InsertCoins();
// 初始化游戏
InitGame();
// 游戏开始
StartGame();
// 游戏结束
EndGame();
}
}

/// <summary>
/// 恐龙快打游戏
/// </summary>
public class KLKDGame : Game
{
public override void InitGame()
{
Console.WriteLine("初始化恐龙快打游戏..");
}

public override void StartGame()
{
Console.WriteLine("开始玩恐龙快打游戏..");
}

public override void EndGame()
{
Console.WriteLine("恐龙快打游戏结束!");
}
}

/// <summary>
/// 三国无双游戏
/// </summary>
public class SGWSGame : Game
{
public override void InitGame()
{
Console.WriteLine("初始化三国无双..");
}

public override void StartGame()
{
Console.WriteLine("开始玩三国无双..");
}

public override void EndGame()
{
Console.WriteLine("三国无双游戏结束!");
}
}

客户端调用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Program
{
static void Main(string[] args)
{
// 玩恐龙快打
Game klkdGame = new KLKDGame();
klkdGame.Play();
Console.WriteLine();

// 玩三国无双
Game sgwsGame = new SGWSGame();
sgwsGame.Play();

Console.ReadKey();
}
}

运行程序:

在游戏厅打游戏的例子中,游戏抽象类的Play方法就是模板方法,这个方法定义了玩游戏的步骤,不管玩什么游戏都必须按照这个流程进行。

小结

上边例子的类图:

模板方法模式的应用场景

模板方法模式在抽象类中定义执行的方法和步骤,子类按需重写各个步骤的方法,从而满足具体的需求。某些行为可以分步执行且执行的步骤固定时可以考虑使用模板方法模式。

模板方法模式的优点

模板方法的行为由父类控制,子类实现,提取了公共代码,便于维护。

模板方法模式的缺点

每一种具体的实现都需要一个子类实现,可能会导致子类过多。

0%