**意图:**定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
**主要解决:**一些方法通用,却在每一个子类都重新写了这一方法。
**何时使用:**有一些通用的方法。
**如何解决:**将这些通用算法抽象出来。
**关键代码:**在抽象类实现,其他步骤在子类实现。
**应用实例: **
1、在造房子的时候,地基、走线、水管都一样,只有在建筑的后期才有加壁橱加栅栏等差异。
2、西游记里面菩萨定好的 81 难,这就是一个顶层的逻辑骨架。
3、spring 中对 Hibernate 的支持,将一些已经定好的方法封装起来,比如开启事务、获取 Session、关闭 Session 等,程序员不重复写那些已经规范好的代码,直接丢一个实体就可以保存。
优点:
1、封装不变部分,扩展可变部分。
2、提取公共代码,便于维护。
3、行为由父类控制,子类实现。
**缺点:**每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。
使用场景:
1、有多个子类共有的方法,且逻辑相同。
2、重要的、复杂的方法,可以考虑作为模板方法。
我们将创建一个定义操作的 Game 抽象类,其中,模板方法不能被重写。Cricket 和 Football 是扩展了 Game 的实体类,它们重写了抽象类的方法。
namespace 模板模式
{
///
/// 步骤 1
///创建一个抽象类,它的模板方法不能被重写。
///
public abstract class Game
{
public abstract void initialize();
public abstract void startPlay();
public abstract void endPlay();
//模板
public void play()
{
//初始化游戏
initialize();
//开始游戏
startPlay();
//结束游戏
endPlay();
}
}
///
/// 步骤 2
///创建扩展了上述类的实体类
///
public class Cricket : Game
{
public override void endPlay() {
Console.WriteLine("Cricket Game Finished!");
}
public override void initialize() {
Console.WriteLine("Cricket Game Initialized! Start playing.");
}
public override void startPlay() {
Console.WriteLine("Cricket Game Started. Enjoy the game!");
}
}
public class Football : Game
{
public override void endPlay()
{
Console.WriteLine("Football Game Finished!");
}
public override void initialize()
{
Console.WriteLine("Football Game Initialized! Start playing.");
}
public override void startPlay()
{
Console.WriteLine("Football Game Started. Enjoy the game!");
}
}
///
/// 步骤 3
///使用 Game 的模板方法 play() 来演示游戏的定义方式。
///
class Program
{
static void Main(string[] args)
{
Game game = new Cricket();
game.play();
Console.WriteLine("");
game = new Football();
game.play();
Console.ReadKey();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TemplateMethodPattern
{
///
/// 1 抽象方法/虚方法/普通方法
/// 2 模板方法设计模式
/// 3 钩子方法
///
class Program
{
static void Main(string[] args)
{
try
{
Console.WriteLine("欢迎来到.net高级班公开课之设计模式特训,今天是Eleven老师为大家带来的模板方法模式");
//MethodTest.Show();
//Client client = new Client();
//client.Query(387, "天道无情", "123456");
{
Client client = new ClientCurrent();
client.Query(387, "天道无情", "123456");
}
{
Client client = new ClientRegular();
client.Query(448, "一点半", "000000");
}
{
Client client = new ClientVip();
client.Query(259, "Gain", "251146");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.Read();
}
}
///
/// 银行客户端
///
public abstract class Client
{
public void Query(int id, string name, string password)
{
if (this.CheckUser(id, password))
{
double balance = this.QueryBalance(id);
double interest = this.CalculateInterest(balance);
this.Show(name, balance, interest);
}
else
{
Console.WriteLine("账户密码错误");
}
}
public bool CheckUser(int id, string password)
{
return DateTime.Now < DateTime.Now.AddDays(1);
}
public double QueryBalance(int id)
{
return new Random().Next(10000, 1000000);
}
///
/// 活期 定期 利率不同
///
///
///
public abstract double CalculateInterest(double balance);
public virtual void Show(string name, double balance, double interest)
{
Console.WriteLine("尊敬的{0}客户,你的账户余额为:{1},利息为{2}",
name, balance, interest);
}
//private void Show(string name, double balance, double interest)
//{
// Console.WriteLine("尊贵的{0} vip客户,您的账户余额为:{1},利息为{2}",
// name, balance, interest);
//}
}
///
/// VIP
///
public class ClientVip : Client
{
///
/// 活期 定期 利率不同
///
///
///
public override double CalculateInterest(double balance)
{
return balance * 0.005;
}
public override void Show(string name, double balance, double interest)
{
Console.WriteLine("尊贵的{0} vip客户,您的账户余额为:{1},利息为{2}",
name, balance, interest);
}
}
public class ClientRegular : Client
{
///
/// 活期 定期 利率不同
///
///
///
public override double CalculateInterest(double balance)
{
return balance * 0.003;
}
}
}