行为型设计模式之模版方法模式:
一、含义
有一个或几个模版方法(固定的逻辑),模版方法是对各个基本方法(可变可扩展的基本操作)的调度。
模版方法和基本方法实现了对一系列操作的固定部分与可变部分的分离。
二、代码说明
1.主要有两类方法:
1)基本方法
基本方法也叫做基本操作,是由子类实现的方法,并且在模版方法被调用
2)模版方法
可以有一个或几个,一般是一个具体方法,也就是一个框架,实现对基本方法的调度,完成固定的逻辑(由于是固定的逻辑,为防止恶意操作,一般模版方法都加上final关键字,不允许被覆写)
2.在用C实现过程中也是参考这种思想,不过C中无super,this关键字,导致包含基本方法的实现类无法通过继承抽象类(内部有模版方法)的方式来实现模版方法对基本方法的调用,因此使用传递接口的方式实现模版方法对基本方法的调用,同时包含模版方法的实现类采用单例模式保证不被修改。
以制造悍马为例,具体实现如下:
1)模版方法模式使用场景:
1 /***************************************************************************** 2 * Copyright (C) 2017-2018 Hanson Yu All rights reserved. 3 ------------------------------------------------------------------------------ 4 * File Module : TemplateMethodPatternUsage.c 5 * Description : 模版方法模式的使用 6 7 book@book-desktop:/work/projects/test/DesignPatterns$ gcc -o TemplateMethodPatternUsage 8 HummerH1Model.c HummerH2Model.c TemplateMethodPattern.c TemplateMethodPatternUsage.c 9 book@book-desktop:/work/projects/test/DesignPatterns$ ./TemplateMethodPatternUsage 10 HummerH1 start... 11 HummerH1 engine boom... 12 HummerH1 alarm... 13 HummerH1 stop... 14 HummerH2 start... 15 HummerH2 engine boom... 16 HummerH2 alarm... 17 HummerH2 stop... 18 19 * Created : 2017.07.12. 20 * Author : Yu Weifeng 21 * Function List : 22 * Last Modified : 23 * History : 24 ******************************************************************************/ 25 #include"stdio.h" 26 #include"malloc.h" 27 #include"stdlib.h" 28 #include"string.h" 29 #include"TemplateMethodPattern.h" 30 31 32 33 34 /***************************************************************************** 35 -Fuction : main 36 -Description : 37 -Input : 38 -Output : 39 -Return : 40 * Modify Date Version Author Modification 41 * ----------------------------------------------- 42 * 2017/07/12 V1.0.0 Yu Weifeng Created 43 ******************************************************************************/ 44 int main(int argc,char **argv) 45 { 46 T_HummerModel tHummerModel=newHummerH1Model; 47 48 g_tHummerDemonstration.Run(&tHummerModel); 49 50 tHummerModel=(T_HummerModel)newHummerH2Model; 51 g_tHummerDemonstration.Run(&tHummerModel); 52 53 return 0; 54 }
2)被调用者:
1 /***************************************************************************** 2 * Copyright (C) 2017-2018 Hanson Yu All rights reserved. 3 ------------------------------------------------------------------------------ 4 * File Module : TemplateMethodPattern.c 5 * Description : 模版方法模式 6 主要放模版方法,同时模版方法调用各个基本方法 7 ,所以也可以改名为TemplateMethod.c 8 为统一名称,本文件也是模版方法模式的核心故还是 9 命名为TemplateMethodPattern.c 10 11 * Created : 2017.07.12. 12 * Author : Yu Weifeng 13 * Function List : 14 * Last Modified : 15 * History : 16 ******************************************************************************/ 17 #include"stdio.h" 18 #include"malloc.h" 19 #include"stdlib.h" 20 #include"string.h" 21 #include"TemplateMethodPattern.h" 22 23 static void HummerRun(T_HummerModel *i_ptHummerModel); 24 25 const T_HummerDemonstration g_tHummerDemonstration={ 26 .Run=HummerRun, 27 28 }; 29 30 /***************************************************************************** 31 -Fuction : HummerRun 32 -Description : 公有函数 33 -Input : 34 -Output : 35 -Return : 36 * Modify Date Version Author Modification 37 * ----------------------------------------------- 38 * 2017/07/12 V1.0.0 Yu Weifeng Created 39 ******************************************************************************/ 40 static void HummerRun(T_HummerModel *i_ptHummerModel) 41 { 42 i_ptHummerModel->Start(); 43 i_ptHummerModel->EngineBoom(); 44 i_ptHummerModel->Alarm(); 45 i_ptHummerModel->Stop(); 46 }
1 /***************************************************************************** 2 * Copyright (C) 2017-2018 Hanson Yu All rights reserved. 3 ------------------------------------------------------------------------------ 4 * File Module : TemplateMethodPattern.h 5 * Description : 模版方法模式 6 主要放模版方法,同时模版方法调用各个基本方法 7 ,所以也可以改名为TemplateMethod.h 8 为统一名称,本文件也是模版方法模式的核心故还是 9 命名为TemplateMethodPattern.h 10 11 * Created : 2017.07.12. 12 * Author : Yu Weifeng 13 * Function List : 14 * Last Modified : 15 * History : 16 ******************************************************************************/ 17 #ifndef TEMPLATE_METHOD_PATTERN_H 18 #define TEMPLATE_METHOD_PATTERN_H 19 20 typedef struct HummerModel//以制造悍马为例 21 { 22 void (*Start)(); 23 void (*EngineBoom)(); 24 void (*Alarm)(); 25 void (*Stop)(); 26 }T_HummerModel;//抽象悍马模型 27 28 29 typedef struct HummerDemonstration//悍马模型演示 30 {//书上基本方法和模版方法合并,通过继承扩展(只覆写基本方法),C无super this无法如此使用, 31 void (*Run)(T_HummerModel *i_ptHummerModel);//因此演示类和模型类不合并更好,如果合并则初始化时需要先有 32 }T_HummerDemonstration;//演示类和模型类的对象,最重要的是当模型对象更换时 33 //需要再次对演示类和模型类的合并累赋值,多次修改合并类(合并类里面有演示类也就是模版方法) 34 //即多次修改模版方法(也暴露了模版方法),显然这是不合适的(除非团队规定类中的模版方法不可覆写,但显然不适用于所有人) 35 //模版方法一般是固定的,是不允许覆写即修改的 36 //同时分为基本方法和模版方法两个类,也实现了基本方法扩展 37 //模版方法关闭修改(单例模式则无法修改) 38 39 //void HummerRun(T_HummerModel *i_ptHummerModel); 40 //#define newHummerDemonstration {HummerRun} 41 extern const T_HummerDemonstration g_tHummerDemonstration;//使用单例模式防止恶意修改固定逻辑的模版方法 42 43 44 45 void HummerH1ModelStart(); 46 void HummerH1ModelEngineBoom(); 47 void HummerH1ModelAlarm(); 48 void HummerH1ModelStop(); 49 #define newHummerH1Model {HummerH1ModelStart,HummerH1ModelEngineBoom, 50 HummerH1ModelAlarm,HummerH1ModelStop} 51 52 void HummerH2ModelStart(); 53 void HummerH2ModelEngineBoom(); 54 void HummerH2ModelAlarm(); 55 void HummerH2ModelStop(); 56 #define newHummerH2Model {HummerH2ModelStart,HummerH2ModelEngineBoom, 57 HummerH2ModelAlarm,HummerH2ModelStop} 58 59 #endif
1 /***************************************************************************** 2 * Copyright (C) 2017-2018 Hanson Yu All rights reserved. 3 ------------------------------------------------------------------------------ 4 * File Module : HummerH1Model.c 5 * Description : H1型号悍马模型 6 * Created : 2017.07.12. 7 * Author : Yu Weifeng 8 * Function List : 9 * Last Modified : 10 * History : 11 ******************************************************************************/ 12 #include"stdio.h" 13 #include"malloc.h" 14 #include"stdlib.h" 15 #include"string.h" 16 #include"TemplateMethodPattern.h" 17 18 19 20 21 22 /***************************************************************************** 23 -Fuction : HummerH1ModelStart 24 -Description : 公有函数 25 -Input : 26 -Output : 27 -Return : 28 * Modify Date Version Author Modification 29 * ----------------------------------------------- 30 * 2017/07/12 V1.0.0 Yu Weifeng Created 31 ******************************************************************************/ 32 void HummerH1ModelStart() 33 { 34 printf("HummerH1 start... "); 35 } 36 37 /***************************************************************************** 38 -Fuction : HummerH1ModelEngineBoom 39 -Description : 公有函数 40 -Input : 41 -Output : 42 -Return : 43 * Modify Date Version Author Modification 44 * ----------------------------------------------- 45 * 2017/07/12 V1.0.0 Yu Weifeng Created 46 ******************************************************************************/ 47 void HummerH1ModelEngineBoom() 48 { 49 printf("HummerH1 engine boom... "); 50 } 51 52 /***************************************************************************** 53 -Fuction : HummerH1ModelAlarm 54 -Description : 公有函数 55 -Input : 56 -Output : 57 -Return : 58 * Modify Date Version Author Modification 59 * ----------------------------------------------- 60 * 2017/07/12 V1.0.0 Yu Weifeng Created 61 ******************************************************************************/ 62 void HummerH1ModelAlarm() 63 { 64 printf("HummerH1 alarm... "); 65 } 66 67 /***************************************************************************** 68 -Fuction : HummerH1ModelStop 69 -Description : 公有函数 70 -Input : 71 -Output : 72 -Return : 73 * Modify Date Version Author Modification 74 * ----------------------------------------------- 75 * 2017/07/12 V1.0.0 Yu Weifeng Created 76 ******************************************************************************/ 77 void HummerH1ModelStop() 78 { 79 printf("HummerH1 stop... "); 80 }
1 /***************************************************************************** 2 * Copyright (C) 2017-2018 Hanson Yu All rights reserved. 3 ------------------------------------------------------------------------------ 4 * File Module : HummerH2Model.c 5 * Description : H2型号悍马模型 6 * Created : 2017.07.12. 7 * Author : Yu Weifeng 8 * Function List : 9 * Last Modified : 10 * History : 11 ******************************************************************************/ 12 #include"stdio.h" 13 #include"malloc.h" 14 #include"stdlib.h" 15 #include"string.h" 16 #include"TemplateMethodPattern.h" 17 18 19 20 21 22 /***************************************************************************** 23 -Fuction : HummerH2ModelStart 24 -Description : 公有函数 25 -Input : 26 -Output : 27 -Return : 28 * Modify Date Version Author Modification 29 * ----------------------------------------------- 30 * 2017/07/12 V1.0.0 Yu Weifeng Created 31 ******************************************************************************/ 32 void HummerH2ModelStart() 33 { 34 printf("HummerH2 start... "); 35 } 36 37 /***************************************************************************** 38 -Fuction : HummerH2ModelEngineBoom 39 -Description : 公有函数 40 -Input : 41 -Output : 42 -Return : 43 * Modify Date Version Author Modification 44 * ----------------------------------------------- 45 * 2017/07/12 V1.0.0 Yu Weifeng Created 46 ******************************************************************************/ 47 void HummerH2ModelEngineBoom() 48 { 49 printf("HummerH2 engine boom... "); 50 } 51 52 /***************************************************************************** 53 -Fuction : HummerH2ModelAlarm 54 -Description : 公有函数 55 -Input : 56 -Output : 57 -Return : 58 * Modify Date Version Author Modification 59 * ----------------------------------------------- 60 * 2017/07/12 V1.0.0 Yu Weifeng Created 61 ******************************************************************************/ 62 void HummerH2ModelAlarm() 63 { 64 printf("HummerH2 alarm... "); 65 } 66 67 /***************************************************************************** 68 -Fuction : HummerH2ModelStop 69 -Description : 公有函数 70 -Input : 71 -Output : 72 -Return : 73 * Modify Date Version Author Modification 74 * ----------------------------------------------- 75 * 2017/07/12 V1.0.0 Yu Weifeng Created 76 ******************************************************************************/ 77 void HummerH2ModelStop() 78 { 79 printf("HummerH2 stop... "); 80 }
3)执行结果:
book@book-desktop:/work/projects/test/DesignPatterns$ gcc -o TemplateMethodPatternUsage
HummerH1Model.c HummerH2Model.c TemplateMethodPattern.c TemplateMethodPatternUsage.c
book@book-desktop:/work/projects/test/DesignPatterns$ ./TemplateMethodPatternUsage
HummerH1 start...
HummerH1 engine boom...
HummerH1 alarm...
HummerH1 stop...
HummerH2 start...
HummerH2 engine boom...
HummerH2 alarm...
HummerH2 stop...
4)详细代码:
https://github.com/fengweiyu/DesignThinking/tree/master/DesignPatterns/BehavioralDesignPatterns/TemplateMethodPattern
三、使用场景
1.多个子类(实现类)有公有的方法,并且逻辑基本相同时
2.重要、复杂的算法,可以把核心算法设计为模版方法,周边的相关细节功能则由各个子类(实现类)实现
3.重构时,模版方法模式是一个经常使用的模式,把相同的代码抽取到父类(模版方法)中,然后通过钩子函数(由子类覆写,模版方法会调用这个钩子函数进行一些判断操作从而改变模版方法的执行逻辑)约束其行为
四、优点
1.封装不变部分(模版方法),扩展可变部分(基本方法)
2.提取公共部分代码,便于维护
3.行为(基本方法)由模版方法控制,子类(实现类)实现,符合开闭原则
五、缺点
1.抽象类定义了部分抽象方法,由子类实现,子类执行的结果影响了父类的结果,也就是子类对父类产生了影响(也由此,模版方法模式也用于父类依赖子类的场景),这在复杂的项目中,会带来代码阅读的难度,而且也会让新手产生不适感