c++ 设计模式3 (重构技法 Template Method)
1. 重构
面向对象设计模式是“好的面向对象设计”,所谓“好的面向对象设计”指的是那些可以满足
“应对变化,提高复用”的设计。
设计模式的要点是“寻找变化点,然后在变化点处应用设计模式,从而更好地理解需求的变化”
“什么时候、什么地点应设计模式”比“理解设计模式结构本身”更为重要。
设计模式的应用不宜先入为主,一上来就使用设计模式是对设计模式的最大误用。没有一部到位
的设计模式。敏捷软件开发提倡“Refactoring to Patterns”是目前普遍公认的最好的使用
设计模式的方法。
2 重构关键技法
技法与原则比某一个单纯的模式重要。
1) 静态 -> 动态
2)早绑定 -> 晚绑定
3) 继承 -> 组合
4) 编译时依赖 -> 运行时依赖
5) 紧耦合 -> 松耦合
3. 组件协作类模式(Template Method, Strategy, Observer)
现在软件专业分工之后的第一个结果是“框架与应用程序的划分”,“组件协作”模式通过晚期绑定,
来实现框架与应用的松耦合,是二者之间协作时常用的模式。
3.1 Template Method
动机: 在软件构建过程中,对于某一项任务,它常常有稳定的整体操作结构,但各个子步骤却有很多改变的需求,或者由于固有的原因(比如框架与应用之间的关系)而无法和任务的整体结构同时实现。
如何在确定稳定操作结构的前提下,来灵活应对各个子步骤的变化或晚期实现需求?
代码实例:
方法2 相对于 方法1,由程序库开发人员实现程序主流程,留下虚函数step2, step4,供应用程序开发人员晚绑定实现。
如图所示:
回到Template Method定义:
定义一个操作的算法的骨架(稳定),而将一些步骤延迟(变化)到子类中。Template Method使得子类可以不改变(复用)一个算法的结构即可重定义(override)该算法的某些特定步骤。
类图关系:
红色稳定,蓝色变化。
要点总结:
Template Method模式是一种非常基础性的设计模式,在面向对象系统中有着大量的应用。它用最简洁的机制(虚函数的多态性)为很多应用程序框架提供了灵活的拓展点,是代码复用方面的基本实现结构;
除了可以灵活应对子步骤的变化外,”不要调用我,让我来调用你“的反向控制结构是Template Method的典型应用;
在具体实现方面,被Template Method调用的虚方法可以具有实现,也可以没有任何实现(抽象方法,纯虚方法),但一般推荐将它们设置为protected 方法。
1 //程序库开发人员 2 //template_lib1.cpp 3 class Library{ 4 5 public: 6 void Step1(){ 7 //... 8 } 9 10 void Step3(){ 11 //... 12 } 13 14 void Step5(){ 15 //... 16 } 17 }; 18 19 //应用程序开发人员 20 //template_app1.cpp 21 class Application{ 22 public: 23 bool Step2(){ 24 //... 25 } 26 27 void Step4(){ 28 //... 29 } 30 }; 31 32 int main() 33 { 34 Library lib(); 35 Application app(); 36 37 lib.Step1(); 38 39 if (app.Step2()){ 40 lib.Step3(); 41 } 42 43 for (int i = 0; i < 4; i++){ 44 app.Step4(); 45 } 46 47 lib.Step5(); 48 49 } 50 51 //程序库开发人员 52 //template_lib1.cpp 53 class Library{ 54 public: 55 //稳定 template method
//稳定中有变化,很多设计模式的代码结构
56 void Run(){ 57 58 Step1(); 59 60 if (Step2()) { //支持变化 ==> 虚函数的多态调用 61 Step3(); 62 } 63 64 for (int i = 0; i < 4; i++){ 65 Step4(); //支持变化 ==> 虚函数的多态调用 66 } 67 68 Step5(); 69 70 } 71 virtual ~Library(){ } 72 73 protected: 74 75 void Step1() { //稳定 76 //..... 77 } 78 void Step3() {//稳定 79 //..... 80 } 81 void Step5() { //稳定 82 //..... 83 } 84 85 virtual bool Step2() = 0;//变化 86 virtual void Step4() =0; //变化 87 }; 88 89 //应用程序开发人员 90 //template_app1.cpp 91 class Application : public Library { 92 protected: 93 virtual bool Step2(){ 94 //... 子类重写实现 95 } 96 97 virtual void Step4() { 98 //... 子类重写实现 99 } 100 }; 101 102 103 104 105 int main() 106 { 107 Library* pLib=new Application(); 108 lib->Run(); 109 110 delete pLib; 111 } 112 }