C++设计模式十--TemplatePattern(模板方法模式)
来源:互联网 发布:穿越火线fps优化器 编辑:程序博客网 时间:2024/06/05 17:15
定义
模板方法模式在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
要点
1.这个方法将算法定义成一组步骤,其中任何步骤都可以是抽象的,由子类负责实现。这样可以确保算法的结果不变,同时由子类提供部分实现。
2.模板方法为我们提供了一种代码复用的重要技巧。
3.策略模式和模板方法模式都封装算法,策略用组合,模板方法用继承。
4.工厂方法模式是模板方法的一种特殊版本。
类图
AbstractClass:模板方法抽象类。
ConcreteClass1/ConcreteClass2:具体类,可以有许多。每个类都实现了模板方法所需的全部操作。
钩子
钩子是一种被声明在抽象类中的方法,但只有空的或默认的实现。钩子的用法主要由以下两点:
1.钩子可以让子类实现算法中可选的部分;
2.钩子能够让子类有机会对模板方法中某些即将发生的(或刚刚发生的)步骤做出反应。
下面示例中CoffeeVeverage.h文件中实现了钩子,子类重写方法 virtual bool customerWantsCondiments()
(改变返回值返回值)就能够控制 void addCondiments()
方法是否会被父类调用。
设计原则
好莱坞原则:别调用我们,我们会调用你。
1.好莱坞原则允许低层组件将自己挂钩到系统上,但高层组件会决定什么时候和怎样使用这些低层组件。
2.决策权应该放在高层模块中,以便决定如何以及何时调用调用低层模块。
3.低层模块并不是完全不能调用高层的方法,低层组件结束是往往会调用从超类中继承来的方法。应该避免高层和低层组件之间有明显的环状依赖。
示例
现实现上图所示算法:
CoffeeVeverage.h
#ifndef COFFEINEBEVERAGE_H#define COFFEINEBEVERAGE_H#include <iostream>using std::cout;using std::cin;using std::endl;// 模板方法类class CoffeineBeverage{public: CoffeineBeverage(){} virtual ~CoffeineBeverage(){} void prepareRecipe() { boilWater(); brew(); pourInCup(); if (customerWantsCondiments()) { addCondiments(); } } virtual void brew() = 0; virtual void addCondiments() = 0; void boilWater() { cout << "Boiling water" << endl; } void pourInCup() { cout << "Pouring into cup" << endl; } virtual bool customerWantsCondiments() // 钩子 { return true; }};#endif
Tea.h
#ifndef TEA_H#define TEA_H#include <string>#include "CaffeineBeverage.h"using std::string;// 茶类(具体类)class Tea : public CoffeineBeverage{public: Tea(){} ~Tea(){} void brew() { cout << "Steeping the tea" << endl; } void addCondiments() { cout << "Adding Lemon" << endl; } bool customerWantsCondiments() { string ret = gerUserInput(); if ("y" == ret) { return true; } else { return false; } }private: string gerUserInput() { string ret = ""; cout << "Would you like lemon with your tea (y/n)?" << endl; cin >> ret; if ("" == ret) { return "n"; } return ret; }};#endif
Coffee.h
#ifndef COFFEE_H#define COFFEE_H#include <string>#include "CoffeineBeverage.h"using std::string;// 咖啡类(具体类)class Coffee : public CoffeineBeverage{public: Coffee(){} ~Coffee(){} void brew() { cout << "Dripping Coffee through filter" << endl; } void addCondiments() { cout << "Adding Sugar and Milk" << endl; } bool customerWantsCondiments() { string ret = gerUserInput(); if ("y" == ret) { return true; } else { return false; } }private: string gerUserInput() { string ret = ""; cout << "Would you like mild and sugar with your coffee (y/n)?" << endl; cin >> ret; if ("" == ret) { return "n"; } return ret; }};#endif
main.cpp
#include "CoffeineBeverage.h"#include "Coffee.h"#include "Tea.h"int main(){ Tea* tea = new Tea(); Coffee* coffee = new Coffee(); cout << "\nMaking tea ..." << endl; tea->prepareRecipe(); cout << "\nMaking coffee ..." << endl; coffee->prepareRecipe();}
Makefile
CXX = g++CFLAGS = -WallLDFLAGS = target = ressrcs = main.cppobjs = $(srcs:.cpp=.o)headers = $(wildcard *.h).PHONY: allall: $(target)$(target): $(objs) $(headers) $(CXX) $(LDFLAGS) -o $(target) $(objs)$(objs):%.o:%.cpp $(CXX) $(CFLAGS) -c -o $@ $<clean: rm -f $(target) *.o
测试
测试结果如下图所示:
如上图所示,在茶和咖啡都有一次询问是否加入“调味品”,根据用户输入的不同产生了不同的结果,这就是钩子在起作用。
- C++设计模式十--TemplatePattern(模板方法模式)
- 模板模式 TemplatePattern
- 设计模式之十 模板方法模式
- 设计模式_模板方法模式(C++)
- 设计模式之模板方法模式(C++)
- 设计模式——模板方法模式(C++)
- 设计模式(十)工厂方法模式
- 设计模式(十)工厂方法模式
- 大话设计模式十:模板方法模式(考题抄错会做也白搭)
- Java设计模式之十:模板方法模式(Template Method)
- PHP设计模式-模板模式(模板方法模式)
- PHP设计模式-模板模式(模板方法模式)
- 设计模式(7)-模板方法模式
- 【设计模式】-模板方法模式(Template)
- 设计模式(7):模板方法模式
- c++设计模式(模板方法模式)
- 设计模式(18) - 模板方法模式
- 设计模式(4):模板方法模式
- Linux for Ubuntu 国产音乐客户端(网易云)
- git 命令总结
- html 缩写
- golang faygo 框架模板的简单使用
- bzoj4519 [Cqoi2016]不同的最小割 分治最小割 模板
- C++设计模式十--TemplatePattern(模板方法模式)
- 数据结构--概述
- Intent传递List<object>方法
- python之html转docx文件高级用法---使用样式
- 杂谈 | 移动互联网行业迎来存量经营时代(一)——宏观环境
- 如何保护你的隐私(一)
- 数据字典设计实现缓存
- 前端入门篇
- 深入浅析同源策略和跨域访问