Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2084461
  • 博文数量: 414
  • 博客积分: 10312
  • 博客等级: 上将
  • 技术积分: 4921
  • 用 户 组: 普通用户
  • 注册时间: 2007-10-31 01:49
文章分类

全部博文(414)

文章存档

2011年(1)

2010年(29)

2009年(82)

2008年(301)

2007年(1)

分类: C/C++

2009-01-17 08:49:32

Abstract

  template method pattern是我学到第二个pattern,算是一个很容易理解的pattern,但却非常的实用。

  Intent

  对於operation,只先定义好演算法的轮廓,某些步骤则留给子类别去填补,以便在不改变演算法整体架构的情况下让子类别去精链某些步骤。

  其UML表示法

我的Design Pattern之旅[2]:Template Method Pattern (OO)

  在实务上,我们可能本来有一个功能完整的class,但因为『需求改变』,新的class和原来的class几乎60%相同, 只有40%不一样,因此我们希望将60%相同部份的程式留下来,仅改写40%不同的地方。

  如本来某公司只生产『自动泡茶机』,後来为了增加产品线,想生产『自动泡咖啡机』,经过分析,两台机器的架构相似,生产流程也相似。

  自动泡茶机

  step1 : 将开水煮开

  step2 : 将<茶叶>放入开水

  step3 : 将<茶>倒入杯子

  step4 : 加上<柠檬>

  自动泡咖啡机

  step1 : 将开水煮开

  step2 : 将<咖啡粉>放入开水

  step3 : 将<咖啡>倒入杯子

  step4 : 加上<糖>和<奶精>

  很明显的step1相同,但step2 ~ step4不相同,所以只需改写step2 ~ step4,step1可以继续使用。先设计一个DrinkMachine雏型,定义了生产过程和step1,因为step2 ~ step4各有差异,就留在继承DrinkMachine的class去改写,这就是template method pattern。

我的Design Pattern之旅[2]:Template Method Pattern (OO)

  我们看看这个架构,日後若有新drink加入,DrinkMachine,TeaMachine,CoffeeMachine皆不用修改,符合OCP的closed for modification原则,若要加入新的class,只计程并改写DrinkMachine即可,符合OCP的open for extension原则,所以是非常好维护的架构。

  简言之,template method pattern就是将不同的member function用class包起来,由derived class去改写。

  以下用C++实做template method pattern。

1/**//*
2(C) OOMusou 2007
http://oomusou.cnblogs.com
3
4Filename  : DP_TemplateMethodPattern1.cpp
5Compiler  : Visual C++ 8.0 / BCB 6.0 / gcc 3.4.2 / ISO C++
6Description : Demo how to use Template Method Pattern
7Release   : 03/31/2007 1.0
8*/
9
10#include
11
12using namespace std;
13
14class DrinkMachine {
15public:
16 void makeDrink();
17
18protected:
19 void boilWater() { cout << "boil some water" << endl; }
20 virtual void doPutIngredient() const = 0;
21 virtual void doPourInCup() const = 0;
22 virtual void doAddFlavoring() const = 0;
23};
24
25void DrinkMachine::makeDrink() {
26 this->boilWater();
27 this->doPutIngredient();
28 this->doPourInCup();
29 this->doAddFlavoring();
30}
31
32class TeaMachine : public DrinkMachine {
33protected:
34 void doPutIngredient() const { cout << "steep tea in boiling water" << endl; }
35 void doPourInCup() const { cout << "pour tea in cup" << endl; }
36 void doAddFlavoring() const {cout << "add lemon" << endl; }
37};
38
39class CoffeeMachine : public DrinkMachine {
40protected:
41 void doPutIngredient() const { cout << "brew coffee in boiling water" << endl; }
42 void doPourInCup() const { cout << "pour coffee in cup" << endl; }
43 void doAddFlavoring() const {cout << "add sugar and milk." << endl; }
44};
45
46int main() {
47 cout << "Making Tea" << endl;
48  
49 DrinkMachine *theDrinkMachine = &TeaMachine();
50 theDrinkMachine->makeDrink();
51 
52 cout << endl;
53 
54 cout << "Making Coffee" << endl;
55 theDrinkMachine = &CoffeeMachine();
56 theDrinkMachine->makeDrink();
57}

  执行结果

Making Tea
boil some water
steep tea in boiling water
pour tea in cup
add lemon
  
Making Coffee
boil some water
brew coffee in boiling water
pour coffee in cup
add sugar and milk.

  感谢Quark提供template版本的template method写法

1#include
2
3using namespace std;
4
5template
6class DrinkMachine {
7public:
8 void makeDrink() {
9  T* derived =(T*) this;
10  
11  this->boilWater();
12  derived->doPutIngredient();
13  derived->doPourInCup();
14  derived->doAddFlavoring();
15 } 
16 
17protected:
18 void boilWater() {
19   cout << "boil some water" << endl;
20  }
21};
22
23class TeaMachine : public DrinkMachine {
24friend DrinkMachine;
25protected:
26 void doPutIngredient() const { cout << "steep tea in boiling water" << endl; }
27 void doPourInCup() const { cout << "pour tea in cup" << endl; }
28 void doAddFlavoring() const {cout << "add lemon" << endl; }
29};
30
31class CoffeeMachine:public DrinkMachine {
32friend DrinkMachine;
33protected:
34 void doPutIngredient() const { cout << "brew coffee in boiling water" << endl; }
35 void doPourInCup() const { cout << "pour coffee in cup" << endl; }
36 void doAddFlavoring() const {cout << "add sugar and milk." << endl; }
37};
38
39int main() {
40 cout << "Making Tea" << endl;
41 DrinkMachine *pTeaMachine = &TeaMachine();
42 pTeaMachine->makeDrink();
43 
44 cout << endl;
45 
46 cout << "Making Coffee" << endl;
47 DrinkMachine *pCoffeeMachine = &CoffeeMachine();
48 pCoffeeMachine->makeDrink();
49}
50

  Remark

  strategy和template method目的相同,皆对『新需求』的不同演算法提供『扩充』的机制,但手法却不同,strategy采用object的方式,利用delegation改变algorithm,而template method则采用class的继承方式来改变algorithm,由於用到的是class的inheritance,所以在compile-time就已经决定要override的algorithm,run-time就无法再改了,但strategy用的是object手法,所以在run-time还可以透过换object改变algorithm。

  GoF的原文如下

  Template methods use inheritance to vary part of an algorithm. Strategies use delegation to vary the entire algorithm.

阅读(1341) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~