设计模式之实现---模版方法模式
/*****************************************
baseobject.h
******************************************/
/*
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
我这里写一个非常实用的例子,是我的一个项目的对象基类构造函数的超级简化版本.
这个对象的基类构造函数会调用一个initailize函数来初始化一个对象.
该initailize中有很多步骤,每一个都由其子类来决定如何初始化
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
*/
#pragma once
#include <iostream>
#include <string>
using namespace std;
class CBaseOjbect
{
protected:
string m_Name;
unsigned int m_Age;
/////可选1
string m_compayName;
////可选2
string m_BabyName;
//这里如果是用成员函数的勾子的话,那会是比较麻烦的一件事,
bool m_bHaveChild;
public:
CBaseOjbect() : m_bHaveChild(false){
//initialize(); //切记 不能直接这样调用, 子类还没定义纯虚函数呢!
}
//这就是模版方法
virtual bool initialize(){
//1
InitName();
//2
InitAge();
//用函数勾子来决定是否初使化公司名字
if( haveCompany() )
InitCompany();
/*这里如果是用成员变量的勾子的话,那会是比较麻烦的一件事
这个函数是在基类的构造过程中被调用的, 此时子类对这个成员变量还没有控制权,
也就是说此时子类还没有办法来设置这个成员变量(当然可以通过调用父类的构造函数传进来,
但这并不是一个好的办法,会导致构造函数过度复杂).所以此时这个勾子的值还是基类默认的值.
*/
//用布尔成员变量勾子来决定是否初使化公司名字
if(m_bHaveChild)
InitBabyName();
return true;
}
///////////////////////////////////////////////////////////////////////////////////
//这个例子只是为了说明模版方法的使用,所以这里都是些只能说明问题的方法,不代表任何问题
//step 1
virtual void InitName() = 0;
//step 2
virtual void InitAge() = 0;
//step 3
virtual void InitCompany() = 0;
//step 4
virtual void InitBabyName() = 0;
///////////////////////////////
//用函数勾子来决定是否调用某个步骤, 这个函数不为纯虚函数
virtual bool haveCompany(){
return true; //默认是在某公司工作的.
}
};
/****************************************************
ManWithAll.h
*****************************************************/
/*
这是一个类,要完全初始化所有字段,公司字段由用户决定是否要初始化
*/
#pragma once
#include "baseobject.h"
class CManWithBaby: public CBaseOjbect
{
public:
CManWithBaby() {
//set init
m_bHaveChild = true;
//initialize
initialize();
}
void InitName(){
cout<<"Name: a man with baby"<<endl;
}
void InitAge(){
cout<<"Age: I'm only 31 years old"<<endl;
}
void InitCompany(){
cout<<"Company: I'm on my way to the company!"<<endl;
}
void InitBabyName(){
cout<<"Baby Name: although i have a baby, i wont tell you his(her) name!"<<endl;
}
bool haveCompany(){
//do many things to decided wether this man have company or not
cout<<"do you have company?";
string res;
while(res != "yes" && res!="no")
{
cout<<"yes or no: ";
cin>>res;
}
return (res == "yes") ? true : false;
}
};
class CManWithoutBaby: public CBaseOjbect
{
public:
CManWithoutBaby() {
//initialize
initialize();
}
void InitName(){
cout<<"Name: a man without baby"<<endl;
}
void InitAge(){
cout<<"Age: I'm only 31 years old"<<endl;
}
void InitCompany(){
cout<<"Company: I'm on my way to the company!"<<endl;
}
void InitBabyName(){
cout<<"Baby Name: I don't have a baby!"<<endl;
}
bool haveCompany(){
//do many things to decided wether this man have company or not
cout<<"do you have company?";
string res;
while(res != "yes" && res!="no")
{
cout<<"yes or no: ";
cin>>res;
}
return (res == "yes") ? true : false;
}
};
/*********************************************
testTemplatePattern.cpp
**********************************************/
/*
设计模式: 模版方法模式
在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使用子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
可以这么说:模板就是一个方法,这个方法将算法定义成一组步骤,其中的任何步骤都可以是抽象的,由子类负责实现。
但如果并不是每个子类都想完全的执行模板类中的方法的话,我们可以利用“勾子”来做这件事。也就是在模板方法中用一个布尔成员变量或者布尔型成员方法来判断是否调个函数。
这个成员变量的值由其子类决定。“勾子”能够作为条件控制。
模板方法模式和策略模式的比较:
1. 策略模式定义一个算法家族,并让这些算法可以与换。正因为每一个算法都被封装起来了,所以那时快以轻易地使用不同的算法。
2. 模板方法模式定义了一个算法的大纲,具体算法的实现是由其子类定义。这么一来,算法中的个别步骤可以有不同的实现细节,但是算法的结构依然维持不变。
这个模式是由底层组件(基类)控制着算法的节奏,由上层组件(子类)来定义具体的实现。当然子类也可以通过勾子技术来对基类定义的算法步骤有一定的可控程度。
工厂方法是模板方法的一种特殊版本
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
我这里写一个非常实用的例子,是我的一个项目的对象基类构造函数的超级简化版本.
这个对象的基类中会有一个initializa()函数,这个函数可以在子类的构造函数中被调用
该initailize中有很多步骤,每一个都由其子类来决定如何初始化
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
*/
#include <iostream>
#include "ManWithAll.h"
using namespace std;
int main()
{
CManWithBaby* mwb = new CManWithBaby();
cout<<"============================="<<endl;
CManWithoutBaby* mwtb = new CManWithoutBaby;
delete mwtb;
delete mwb;
return 0;
}