原文:C#设计模式之十三模板要领模式(Template Method Pattern)【行为型】
一、引言
“布局型”的设计模式已经写完了,从今天我们开始讲“行为型”设计模式。此刻我们开始讲【行为型】设计模式的第一个模式,该模式是【模板要领】,英文名称是:Template Method Pattern。还是老套路,先从名字上来看看。“模板要领”我第一次看到这个名称,我的理解是,有一个要领的名字叫“模板要领”,后来深入学习之后,觉得最初的理解还没错,也可以换个理解要领,有一个要领包罗了一个模板,这个模板是一个算法。在我们的现实生活中有很多例子可以拿来说明这个模式,就拿吃饺子这个工作来说,要想吃到饺子必需颠末三步,第一步是“和面”,第二步是“包馅”,第三步是“煮饺子”,这三步就是一个算法,我们要想吃到差此外面和馅的饺子,对这三步中的任意一步就行操纵就可以,也可以完全界说这三步,下面我们就来看看这个模式的详细介绍吧。
二、模板要领模式的详细介绍
2.1、动机(Motivate)
在软件构建过程中,对付某一项任务,它每每有不变的整体操纵布局,但各个子法式却有很多转变的需求,或者由于固有的原因(好比框架与应用之间的关系)而无法和任务的整体布局同时实现。如安在确定不变操纵布局的前提下,来灵活应对各个子法式的变革或者晚期实现需求?
2.2、意图(Intent)
界说一个操纵中的算法的骨架,而将一些法式延迟到子类中。Template Method使得子类可以不转变一个算法的布局即可重界说该算法的某些特定法式。 ——《设计模式》GoF
2.3、布局图
2.4、模式的构成
模板要领模式参预者:
(1)、抽象类角色(AbstractClass):界说一个模板要领(TemplateMethod),在该要领中包罗着一个算法的骨架,具体的算法法式是PrimitiveOperation1要领和PrimitiveOperation2要领,该抽象类的子类将重界说PrimitiveOperation1和PrimitiveOperation2操纵。
(2)、具体类角色(ConcreteClass):实现PrimitiveOperation1要领和PrimitiveOperation2要领以完成算法中与特定子类(Client)相关的内容。
在模板要领模式中,AbstractClass中的TemplateMethod供给了一个标准模板,该模板包罗PrimitiveOperation1和PrimitiveOperation2两个要领,这两个要领的内容Client可以按照本身的需要重写。
2.5、模板要领模式的具体实现
理解了模板要领的界说之后,自然实现模板要领也不是什么难事了,下面以生活中吃饺子为例来实现模板要领模式。在现实生活中,做饺子的法式都大抵不异,如果我们针对每种饺子的做法都界说一个类,这样在每个类中都有很多不异的代码,为了解决这个问题,我们一般的思路必定是把不异的部分抽象出来到抽象类中去界说,具体子类来实现具体的差别部分,这个思路也正式模板要领的实现精髓地址,具体实现代码如下:
1 namespace 模板要领模式的实现 2 { 3 /// <summary> 4 /// 好吃不如饺子,舒服不如倒着,我最喜欢吃我爸爸包的饺子,今天就拿吃饺子这件事来看看模板要领的实现吧 5 /// </summary> 6 class Client 7 { 8 static void Main(string[] args) 9 { 10 //此刻想吃绿色面的,猪肉大葱馅的饺子 11 AbstractClass fan = new ConcreteClass(); 12 fan.EatDumplings(); 13 14 Console.WriteLine(); 15 //过了段时间,我开始想吃橙色面的,韭菜鸡蛋馅的饺子 16 fan = new ConcreteClass2(); 17 fan.EatDumplings(); 18 19 20 Console.Read(); 21 } 22 } 23 24 25 //该类型就是抽象类角色--AbstractClass,界说做饺子的算法骨架,这里有三法式,固然也可以有多个法式,按照实际需要而定 26 public abstract class AbstractClass 27 { 28 //该要领就是模板要领,要领里面包罗了做饺子的算法法式,模板要领可以返回功效,也可以是void类型,视具体情况而定 29 public void EatDumplings() 30 { 31 //和面 32 MakingDough(); 33 //包馅 34 MakeDumplings(); 35 //煮饺子 36 BoiledDumplings(); 37 38 Console.WriteLine("饺子真好吃!"); 39 } 40 41 //要想吃饺子第一步必定是“和面”---该要领相当于算法中的某一步 42 public abstract void MakingDough(); 43 44 //要想吃饺子第二部是“包饺子”---该要领相当于算法中的某一步 45 public abstract void MakeDumplings(); 46 47 //要想吃饺子第三部是“煮饺子”---该要领相当于算法中的某一步 48 public abstract void BoiledDumplings(); 49 } 50 51 //该类型是具体类角色--ConcreteClass,我想吃绿色面皮,猪肉大葱馅的饺子 52 public sealed class ConcreteClass : AbstractClass 53 { 54 //要想吃饺子第一步必定是“和面”---该要领相当于算法中的某一步 55 public override void MakingDough() 56 { 57 //我想要面是绿色的,绿色健康嘛,就可以在此步定制了 58 Console.WriteLine("在和面的时候插手芹菜汁,和好的面就是绿色的"); 59 } 60 61 //要想吃饺子第二部是“包饺子”---该要领相当于算法中的某一步 62 public override void MakeDumplings() 63 { 64 //我想吃猪肉大葱馅的,在此步就可以定制了 65 Console.WriteLine("农家猪肉和农家大葱,制作成馅"); 66 } 67 68 //要想吃饺子第三部是“煮饺子”---该要领相当于算法中的某一步 69 public override void BoiledDumplings() 70 { 71 //我想吃大铁锅煮的饺子,有家的味道,在此步就可以定制了 72 Console.WriteLine("用我家的大铁锅和大木材煮饺子"); 73 } 74 } 75 76 //该类型是具体类角色--ConcreteClass2,我想吃橙色面皮,韭菜鸡蛋馅的饺子 77 public sealed class ConcreteClass2 : AbstractClass 78 { 79 //要想吃饺子第一步必定是“和面”---该要领相当于算法中的某一步 80 public override void MakingDough() 81 { 82 //我想要面是橙色的,插手胡萝卜汁就可以。在此步定制就可以了。 83 Console.WriteLine("在和面的时候插手胡萝卜汁,,和好的面就是橙色的"); 84 } 85 86 //要想吃饺子第二部是“包饺子”---该要领相当于算法中的某一步 87 public override void MakeDumplings() 88 { 89 //我想吃韭菜鸡蛋馅的,在此步就可以定制了 90 Console.WriteLine("农家鸡蛋和农家韭菜,制作成馅"); 91 } 92 93 //要想吃饺子第三部是“煮饺子”---该要领相当于算法中的某一步 94 public override void BoiledDumplings() 95 { 96 //此处没要求 97 Console.WriteLine("可以用一般煤气和不粘锅煮就可以"); 98 } 99 } 100 }