文章目录

  • 一、设计模式-模板方法
    • 1、简单介绍
    • 2、框架演示
    • 3、实际案例

一、设计模式-模板方法

1、简单介绍

简单来说,就是先在父类FFF中定义好一个函数AAA,然后这个函数AAA代表了一个操作MMM,函数AAA的内部调用了若干个已经实现的函数BiB_iBi​、未实现的函数CiC_iCi​,BiB_iBi​和CiC_iCi​这些函数在函数AAA中的执行流程构成了函数AAA的整体框架,其中

  • 函数AAA象征了操作MMM的整体流程
  • 函数BiB_iBi​象征了操作MMM中既定的步骤,所有不同主体的操作MMM中的这些步骤都相同
  • 函数CiC_iCi​象征了操作MMM中未定的步骤,存在不同主体的操作MMM中的这些步骤不相同

这样的设计下,我们可以根据不同的场景来设计子类SiS_iSi​的函数CiC_iCi​的具体内容。父类FFF往往是抽象类。

模板方法的整体思想是,对于某个操作,先在父类中定义好其算法的整体框架,然后将框架中的步骤延迟到子类里面去实现。

这样做的好处是,算法的整体框架已经定下来了,对于相似操作的不同步骤可以在子类中给出具体的实现。

  • 在子类中不需要重写出共同的重复步骤,代码复用性强
  • 在子类中也改变不了整体框架(或者说是运行流程),整体结构性强。

2、框架演示

UML图示

代码

// 抽象父类——F
class F
{public:void process_whole()  // 整体的操作{common_step_1();      // 共同步骤1common_step_2();      // 共同步骤2especial_step_1();    // 【待实现】不同步骤1especial_step_2();    // 【待实现】不同步骤2common_step_etc();    // 共同步骤...especial_step_etc();  // 【待实现】不同步骤...especial_step_m();    // 【待实现】不同步骤mcommon_step_n();      // 共同步骤n}
protected:virtual void especial_step_1() = 0;    // 不同步骤1virtual void especial_step_2() = 0;    // 不同步骤2virtual void especial_step_etc() = 0;  // 不同步骤...virtual void especial_step_m() = 0;    // 不同步骤m
private:void common_step_1() {  }    // 共同步骤1void common_step_2() {  }    // 共同步骤2void common_step_etc() {  }  // 共同步骤...void common_step_n() {  }    // 共同步骤n
};// 实现子类——S1
class S1 : public F
{virtual void especial_step_1(){// 【S1具体实现】不同步骤1}virtual void especial_step_2() = 0{// 【S1具体实现】不同步骤2}virtual void especial_step_etc() = 0{// 【S1具体实现】不同步骤...}virtual void especial_step_m() = 0{// 【S1具体实现】不同步骤m}
};// 实现子类——S2
class S2 : public F
{virtual void especial_step_1(){// 【S2具体实现】不同步骤1}virtual void especial_step_2() = 0{// 【S2具体实现】不同步骤2}virtual void especial_step_etc() = 0{// 【S2具体实现】不同步骤...}virtual void especial_step_m() = 0{// 【S2具体实现】不同步骤m}
};

3、实际案例

案例:

现在设计一个父类为动物饲养员AnimalRaiser,有一个函数feed功能是为动物喂食,喂食的过程分为:

  1. 拿出饭碗
  2. 放上食物
  3. 等待动物食用完毕
  4. 回收饭碗洗干净

由于每个动物食用的食物不同,需要根据动物的种类喂食不同的饲料,比如给狗狗喂食排骨,给猫咪喂食清蒸鱼。(假设其他步骤对所有动物均相同)

另外设计两个类——狗狗饲养员DogRaiser、猫咪饲养员CatRaiser.

UML图示

AnimalRaiser类

  • AnimalRaiser.h

    #ifndef ANIMALRAISER_H
    #define ANIMALRAISER_Hclass AnimalRaiser
    {public:AnimalRaiser();virtual ~AnimalRaiser();void feed();
    protected:virtual void push_food() = 0;
    private:void prepare_bowl();void wait_eat();void clear_bowl();
    };#endif // !ANIMALRAISER_H
    
  • AnimalRaiser.cpp

    #include "pch.h"#include "AnimalRaiser.h"
    #include <iostream>using namespace std;AnimalRaiser::AnimalRaiser()
    {}AnimalRaiser::~AnimalRaiser()
    {}void AnimalRaiser::feed()
    {prepare_bowl();push_food();wait_eat();clear_bowl();
    }void AnimalRaiser::prepare_bowl()
    {cout << "正在准备饭碗..." << endl;
    }void AnimalRaiser::wait_eat()
    {cout << "正在等待食用完毕..." << endl;
    }void AnimalRaiser::clear_bowl()
    {cout << "正在回收饭碗并清洗..." << endl;
    }
    

CatRaiser类

  • CatRaiser.h

    #include "AnimalRaiser.h"#ifndef CATRAISER_H
    #define CATRAISER_Hclass CatRaiser :public AnimalRaiser
    {public:CatRaiser();virtual ~CatRaiser();
    protected:virtual void push_food();
    };#endif // !CATRAISER_H
    
  • CatRaiser.cpp

    #include "pch.h"#include "CatRaiser.h"
    #include <iostream>using namespace std;CatRaiser::CatRaiser()
    {}CatRaiser::~CatRaiser()
    {}void CatRaiser::push_food()
    {cout << "正在往碗里放上猫咪最爱吃的清蒸鱼..." << endl;
    }
    

DogRaiser类

  • DogRaiser.h

    #include "AnimalRaiser.h"#ifndef DOGRAISER_H
    #define DOGRAISER_Hclass DogRaiser :public AnimalRaiser
    {public:DogRaiser();virtual ~DogRaiser();
    protected:virtual void push_food();
    };#endif // !DOGRAISER_H
    
  • DogRaiser.cpp

    #include "pch.h"#include "DogRaiser.h"
    #include <iostream>using namespace std;DogRaiser::DogRaiser()
    {}DogRaiser::~DogRaiser()
    {}void DogRaiser::push_food()
    {cout << "正在往碗里放上狗狗最爱吃的排骨..." << endl;
    }
    

Main

  • Main.cpp

    #include "pch.h"#include "CatRaiser.h"
    #include "DogRaiser.h"
    #include <iostream>using namespace std;int main()
    {CatRaiser cr1;DogRaiser dr1;AnimalRaiser* arp;arp = &cr1;arp->feed();cout << "------------------------------------" << endl;arp = &dr1;arp->feed();return 0;
    }
    

执行结果

正在准备饭碗...
正在往碗里放上猫咪最爱吃的清蒸鱼...
正在等待食用完毕...
正在回收饭碗并清洗...
------------------------------------
正在准备饭碗...
正在往碗里放上狗狗最爱吃的排骨...
正在等待食用完毕...
正在回收饭碗并清洗...

《编码规范和测试方法——C/C++版》作业 ·006——设计模式 · 模板方法相关推荐

  1. 《编码规范和测试方法——C/C++版》作业 ·003——宏定义作用整理、设计删除数组元素的函数

    文章目录 一.宏定义(#define)的作用 1.普通宏 2.带参宏 [注]:特殊用法 3.其他用法和注意点 二.实际问题(函数设计) 1.原题 2.题解参考 (1).面向过程的设计 (2).面向对象 ...

  2. 《编码规范和测试方法——C/C++版》学习笔记 ·001

    文章目录 一.编码规范的目的 二.相关知识补充 1.32位机下C++中各变量占用的字节数 2.按位操作 三.规范事项 1.把常量放在==左边 2.按位位移操作的右操作数必须小于操作的位数 3.不要对有 ...

  3. 《编码规范和测试方法——C/C++版》作业 ·008——编写一个符合依赖倒置原则的简单学生管理系统

    文章目录 问题描述 参考解答 整体架构 UML图 整体代码 MySQL-C-API封装 Model层 Dao层 Service层 Controller层 View层 主程序 测试环境 测试流程 测试效 ...

  4. 《编码规范和测试方法——C/C++版》作业 ·007——C++引入MySQL给C的API并简单封装

    文章目录 问题描述 参考解答 API引入 API测试 一些问题 封装代码 测试环境 测试代码 测试结果 问题描述 使用MySQL为C提供的API,封装出一个访问MySQL数据库的类.要求至少能实现如下 ...

  5. 《编码规范和测试方法——C/C++版》作业 ·005——设计一组员工类

    问题描述 Cola公司的雇员分为以下若干类:ColaEmployee :所有员工总的父类属性:员工的姓名,员工的生日月份方法:getSalary(int month) 根据参数月份来确定工资,如果该月 ...

  6. 《编码规范和测试方法——C/C++版》作业 ·004——设计一个顺序表

    问题描述 实现一个能够实现自动扩容ArrayList类的封装(不使用C++容器),主要至少具有增加.删除.求长的功能 参考解答 ArrayList.h文件 #ifndef ARRAYLIST_H #d ...

  7. 《编码规范和测试方法——C/C++版》作业 ·002——函数返回地址、static关键词用法整理

    文章目录 一.函数返回地址的情形 1.函数返回值为指针 二.static关键字用法整理 1.static全局变量 2.static局部变量 3.static函数 4.类的static成员数据 5.类的 ...

  8. 《编码规范和测试方法——C/C++版》学习笔记 ·002

    文章目录 一.相关知识补充 1.switch接受的参数类型 2.内存分区与数据存放 3.变量的作用域与生命期 4.调试开关的使用 二.规范事项 1.杂项 (1).for循环语句中只出现影响循环控制的变 ...

  9. Android安全编码规范

    1.目的 为使系统开发人员能够编写符合安全要求的代码,以降低代码安全漏洞,减少代码被利用的可能性,从而提升各系统安全水平,符合国家安全合规性要求,保障产品安全稳定运营以及信息安全,特制定本规范. 2. ...

最新文章

  1. nexus 4 下 DualBootInstallation 安装 ubuntu touch
  2. 【数理知识】《数值分析》李庆扬老师-第5章-解线性方程组的直接方法
  3. 震惊!html文件注释也会影响运行代码!(werkzeug.routing.BuildError: Could not build url for endpoint)莫名其妙
  4. Linux+Oracle+12c+RAC+安装配置详细-GI安装
  5. java策略设计模式_Java中的策略设计模式
  6. apache camel_REST与Apache Camel
  7. apk获取服务器时间文件名,如何根据APK文件获取应用程序签名时间
  8. 视网膜New iPad与普通分辨率iPad页面的兼容处理
  9. 变电所自动化系统的电源配置
  10. linux——网络情报收集(总结篇.干货+实战)
  11. python3调用企业微信api
  12. Keil_v5 下生成bin文件+Jflash 下载bin文件
  13. Axure授权码,2021年11月11日亲测有效
  14. Python实现二叉树的前中后序遍历
  15. 自动驾驶应用加速 模拟仿真技术是关键之一
  16. extern int a 和int a的区别
  17. SmartBI常用报表宏代码
  18. 软件工程课堂作业(三)——Right-BICEP软件单元测试
  19. 描述计算机内存的参数,电脑组装内存知识,你不能不知的内存参数介绍
  20. 算法:CLH锁的原理及实现

热门文章

  1. javabean和java类_java对象 POJO和JavaBean的区别
  2. mysql my.ini配置优化_求高手帮我优化一下 mysql 的 my.ini
  3. linux孟庆昌第六章课后题_第六章 参数估计-矩估计:通过课后题理解矩估计
  4. orika java_使用orika进行对象间Mapping
  5. python判断set里是否包含值_【python】判断值是否在list和set的对比以及set的实现原理...
  6. 华为MDC调试工具使用介绍
  7. PAT (Basic Level) Practice (中文)答案合集
  8. pypi的embeddings包踩坑
  9. 第八届“图灵杯”NEUQ-ACM程序设计竞赛个人赛——J题 这是一题简单的模拟
  10. Android之TextView练习