模板?生科的小朋友或许会这样理解,DNA复制或转录时,用来产生互补链的核苷酸序列。在我们的日程生活中,我们也时常与模板打交道,比如有些师哥师姐毕业了,需要写简历应聘,这个时候就有了简历模板;临近毕业大四的孩子,需要准备论文,就有了论文模板,所以,模板的概念就是有一个规定的格式,然后每个人都可以根据自己的需求或情况去更新完善它,例如简历模板,从网上down下来的简历模板的格式都是相同的,要想拿到一份满意的offer,我们首先要根据自己的情况填充不同的内容完成属于自己的简历,拿到那梦寐以求的Offer。
在设计模式中,模板方法模式中模板和生活中模板概念非常类似。模板方法模式——在一个抽象类中定义一个操作中的算法骨架(对应于生活中的大家down的模板),而将一些步骤延迟到子类中去实现(对应于我们根据自己的情况向模板填充内容)。模板方法使得子类可以不改变一个算法的结构前提下,重新定义算法的某些特定步骤,模板方法模式把不变行为搬到超类中,从而去除了子类中的重复代码。来看一下我们模板方法模式的结构图:
![](https://box.kancloud.cn/2015-12-30_568374380f3a1.jpg)
除了简历模板之外,我们再来举一个生活中的故事,而我就是这个故事中傻傻的主角儿,这几天饭卡里没有钱了,人是铁饭是钢,一顿不吃饿得慌,虽然说减肥刻不容缓,可是真理说的好啊,不吃饱哪儿来的力气减肥啊,周二下午四点来到工商银行ATM机钱取钱,奇怪,为什么密码不对呢?无奈,再来一次,就这样连续三次,我的银行卡光荣的被锁住了,拔出银行卡一看,我看见了什么,上面赫然写着,邮政储蓄,原来我把邮政储蓄的卡当成了工行的卡,两个卡的密码不一样,我在工行取钱,插到ATM机的是邮政的卡,按的密码是邮政银行卡的密码,所以,才发生了刚才那不堪回首的一幕,没有办法,去前台把卡给解锁了,这样才能有力气减肥。
来到服务厅,人真多啊,在银行办理业务时,一般我们都按照这样的步骤依次进行,取号排队,办理具体业务,对银行工作人员进行评分,这样一套工作流程不就是我们的模板方法模式?我们先来看看这个例子的类图:
![](https://box.kancloud.cn/2015-12-30_5683743820b2d.jpg)
有了类图,我们的代码需要如何实现呢:
~~~
// 客户端调用
class Client
{
static void Main(string[] args)
{
// 创建一个办业务流程实例并调用模板方法
Business business = new Business();
business. Flow();
Console.Read();
}
}
public abstract class Business
{
// 模板方法,不要把模版方法定义为Virtual或abstract方法,避免被子类重写,防止更改流程的执行顺序
public void Flow()
{
Console.WriteLine("办理业务的一般流程");
this.LineUp(); //取号排队
this.Manage(); //办理具体业务
this.Graded(); //对银行工作人员进行评分
}
// 第一步取号排队
public void LineUp()
{
Console.WriteLine("取号排队");
}
// 第二步办理具体业务
public void Manage()
{
Console.WriteLine("办理具体业务");
}
// 第三步对银行工作人员进行评分
public void Graded()
{
Console.WriteLine("对银行工作人员进行评分");
}
}
// 顾客A
public class Business: Flow
{
public override void Business()
{
Console.WriteLine("顾客A办理业务");
}
}
// 顾客B
public class Business : Flow
{
public override void Business()
{
Console.WriteLine("顾客B办理业务");
}
}
~~~
经过银行姐姐的辛苦工作,我的卡终于解锁了,以后做事情要小心一点,不能这么马虎了,都这么大个人了,是吧,言归正传,模板方法模式--准备一个抽象类,将部分逻辑以具体方法以及具体构造子的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。这就是模版方法模式的用意。设计之旅,未完待续.......