[Head First设计模式]云南米线馆中的设计模式――模版方法模式(一)

2014-11-24 02:45:29 · 作者: · 浏览: 5
引言
第一天上班,没什么任务,就学习了下模版方法模式,这里也是现学现卖,模版方法给我的感觉是似曾相识,总感觉用过,而当时并不知道是模版方法,挺悲催的。年后第一天,吃饭是个大问题,好不容易找到一个米线馆,人非常的多,只能边等边思考模版方法模式了,跟以前一样,对于吃货来说,只有将知识和吃联系在一起,才能记得更牢。
模版方法模式是最为常见的几个模式之一,模版方法模式需要开发抽象类和具体子类的设计师之间的写作。一个设计师负责给出一个算法的轮廓和骨架,另一些设计师负责给出这个算法的各个逻辑步骤。
继承常常作为功能复用的主要工具,这时继承有被滥用的危险。所以,我们有一个设计原则:多用组合,少用继承
继承
是不是继承就根本不应该使用呢?事实上对数据的抽象、继承、封装和多态是面向对象语言的最重要特性。继承不应当被滥用,并不意味着继承根本就不该使用。在GoF书中,绝大多数模式是将依赖于继承的实现转换为基于对象的组合和聚合来实现的。模版方法模式是很少用继承来实现的模式中的一个!而且模版方法模式:鼓励恰当的使用继承。此模式可以用来改写一些拥有相同功能的相关类,将可复用的一般性的行为代码移到基类里面,而把特殊化的行为代码移到子类里面。熟悉模版方法模式便成为一个重新学习继承的好地方。
书中的例子
咖啡因饮料
咖啡类
复制代码
1 public class Coffee
2 {
3 public void PrepareRecipe()
4 {
5 BoilWater();
6 BrewCoffeeGrinds();
7 PourInCup();
8 AddSugarAndMilk();
9 }
10 //每个方法都实现算法中的一个步骤:煮沸水,冲泡咖啡,把咖啡倒进杯子,加糖和牛奶
11 public void BoilWater()
12 {
13
14 Console.WriteLine("Boiling water");
15 }
16 public void BrewCoffeeGrinds()
17 {
18 Console.WriteLine("Dripping Coffee through filter");
19 }
20 public void PourInCup()
21 {
22 Console.WriteLine("Pouring into cup");
23 }
24 public void AddSugarAndMilk()
25 {
26
27 Console.WriteLine("Adding Sugar and Milk");
28 }
29 }
复制代码
茶类
复制代码
1 public class Tea
2 {
3 public void PrepareRecipe()
4 {
5 BoilWater();
6 //第二步和第四步与咖啡的实现不同,其他的都一样
7 SteepTeaBag();
8 PourInCup();
9 AddLemon();
10 }
11 //每个方法都实现算法中的一个步骤:煮沸水,冲泡咖啡,把咖啡倒进杯子,加糖和牛奶
12 public void BoilWater()
13 {
14
15 Console.WriteLine("Boiling water");
16 }
17 //泡茶专用
18 public void SteepTeaBag()
19 {
20 Console.WriteLine("Steeping the tea");
21 }
22 public void PourInCup()
23 {
24 Console.WriteLine("Pouring into cup");
25 }
26 //泡茶专用
27 public void AddLemon()
28 {
29
30 Console.WriteLine("Adding Lemon");
31 }
32 }
复制代码
第一版设计
星巴兹咖啡和茶冲泡的分析
星巴兹咖啡和茶冲泡采用了相同的算法:
把水煮沸
用热水泡咖啡或茶
把饮料倒进杯子
在饮料内加入适当的调料
抽象PrepareRecipe()
1、我们遇到的问题是:茶使用SteepTeaBag()和AddLemon()方法,而咖啡使用BrewCoffeeGrinds()和AddSugarAndMilk()方法。
2、无论是咖啡的冲泡,还是茶的浸泡,都是用沸水泡,我们给它一个新的方法名称,比如说Brew()。同样,无论是咖啡加糖和牛奶,还是茶加柠檬,都是加调料,我们也给它一个新的方法名称AddCondiments()。这样,新的prepareRecipe()方法看起来就象这样:
复制代码
1 public void prepareRecipe()
2 {
3 BoilWater();
4 Brew();
5 PourInCup();
6 AddCondiments();
7 }
复制代码
3、CaffeineBeverage(咖啡因饮料)超类:
复制代码
1 public abstract class CaffeineBeverage
2 {
3 public void PrepareRecipe()
4 {
5 BoilWater();
6 //步骤2和步骤4被泛化为Brew()和AddCondiments()。
7 Brew();
8 PourInCup();
9 AddCondiments();
10 }
11 //这两个方法声明为抽象的,是因为咖啡和茶的做法不同,需要子类实现。
12 public abstract void Brew();
13 public abstract void AddCondiments();
14 public void BoilWater()
15 {
16 Console.WriteLine("Boili