学以致用C++设计模式 “模板方法模式”
时间:2022-07-23
本文章向大家介绍学以致用C++设计模式 “模板方法模式”,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
新品上市
我那位朋友,果然是有雄心壮志的人,这不,最近要开拓汉堡业务,想要有一条流水线生产,又不想太死板,正发愁呢。 正好这天我又到他的店里吃饭,看他眉头紧锁,我便给丫出了个主意,顺便免单。 主意是这样的: 你安排一条流水,把固定步骤定下来,比方说烤面包、烤肉、加奶油、上生菜、面包夹肉。 然后具体用料由具体工作人员来确定,这样不就结了,一条线下来,总体工作步骤一致,但是可以生产各种你要的汉堡。
我们来看一下这个方法,它包含了几个什么因素?首先是汉堡(目的产品),一条主流水、然后是生产人员,生产出各种汉堡。
我们将这个流程画出一个类图来看:
那这个流程不就相当的清楚且简单了吗
代码实现
#include<iostream>
using namespace std;
class abstracthumber {
public:
virtual void bread() = 0;
virtual void barbecue() = 0;
virtual void cream() = 0;
virtual void lettuce() = 0;
void run() //将共同的核心算法流程提炼到抽象类
{
this->bread();
this->barbecue();
this->cream();
this->lettuce();
}
};
//将细节延迟到子类
//这两步便是模板方法模式的精髓
class chicken :public abstracthumber {
public:
void bread() { cout << "鸡腿堡的面包" << endl; }
void barbecue() { cout << "鸡腿堡的鸡腿" << endl; }
void cream() { cout << "鸡腿堡的奶油" << endl; }
void lettuce() { cout << "鸡腿堡的生菜" << endl; }
};
class beef :public abstracthumber {
public:
void bread() { cout << "牛肉堡的面包" << endl; }
void barbecue() { cout << "牛肉堡的鸡腿" << endl; }
void cream() { cout << "牛肉堡的奶油" << endl; }
void lettuce() { cout << "牛肉堡的生菜" << endl; }
};
int main()
{
abstracthumber* a = new chicken();
abstracthumber* b = new beef();
a->run();
b->run();
}
我的思考
这方法挺好,将核心算法和细节实现解耦合,不过也是那个拓展的问题还是会存在。
模板方法模式定义
定义一个操作中的算法的框架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
所以,如果要改算法,那就重构吧。
用武之地
模板方法的有点
- 封装不变部分,拓展可变部分(把认为是不变部分的算法封装到父类实现,而可变部分可以通过继承来继续拓展。如果要在来个新产品,虾堡,知道怎么做吧,可以自己做一下)
- 提取公共部分代码,便于维护。想想看,那个run要是放到子类,那要修改会有几倍工作量?
- 行为由父类控制,子类实现。
模板方法的缺点
- 子类对父类产生了影响,这会加大代码的理解难度,对新手不太友好。
使用场景
- 多个子类有共同的方法,并且逻辑基本相同。
- 重要、复杂的算法,可以把核心算法设计为模板方法,周边细节由各个子类实现。
- 重构时,模板方法模式是一个常见的模式。
模板方法模式的拓展
可以自己去试试写一个,造车的模板。
今天就到这里,下一篇会是什么嘞?对,和模板方法模式相似度挺高的“建造者模式”!
- GO语言文件的创建与打开实例分析
- Go语言单链表实现方法
- Go语言实现AzDG可逆加密算法实例
- 剖析Go编写的Socket服务器模块解耦及基础模块的设计
- Golang中的sync.WaitGroup用法实例
- Go 语言实现 MapReduce 框架
- Performance Schema使用简介(一)
- golang 垃圾回收 gc
- Go语言服务器开发之简易TCP客户端与服务端实现方法
- 移动搜索SEO分享:PHP自动生成百度开放适配及360移动适配专用的Sitemap文件
- 分享两种外链跳转方法,可避免权重流失。
- go语言十大排序算法总结
- 网站安全检测提示“页面异常导致本地路径泄漏”的解决办法
- Go语言归并排序算法实现
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- PAT (Advanced Level) Practice 1040 Longest Symmetric String (25分)
- 【Java】23 函数式编程
- 【Java】24 常用函数式接口
- mvnw,到底是什么鬼?
- 【Java】25 Stream 流
- Codeforces Round #615 (Div. 3)D. MEX maximizing
- PAT (Advanced Level) Practice 1039 Course List for Student (25分)
- Codeforces Round #615 (Div. 3) E. Obtain a Permutation
- 数据结构实验完结撒花之内部排序比较
- Codeforces Round #615 (Div. 3) F. Three Paths on a Tree
- Matlab 内联函数及匿名函数
- 渗透测试 | 内网信息收集
- 浅谈 CSS 的用法
- PAT (Advanced Level) Practice 1049 Counting Ones (30分)
- 用递归的思想实现二叉树前、中、后序迭代遍历