概念:
模板模式定义了一个操作中的算法骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
模板模式是非常常用和结构简单的行为型设计模式,就连刚开始学习面向对象继承和多态知识的程序员也会不知不觉中使用到这个设计模式。它的核心就是提高代码的复用性和系统的灵活性,是基于继承的代码复用技术。
例子:
一个鲜活简单的例子总能让人轻松地理解晦涩的概念。我们来看看一个关于汽车价格的模板模式。
我们知道,汽车的品牌和质量,决定了它的价格。就像宝马(BMW),法拉利(Ferrali)和奔驰(Benz)三辆汽车,它们的价格肯定是不一样的。那如果想要知道价格可以询问销售人员等等,但是在计算机里,我们可不能直接询问销售人员啊!
对于它们来说,虽然价格不同,但是获取价格这个操作却是一样的。我们可以设置一个父类Car,它有一个模板函数框架(Template Method),把获取价格GetPrice这个操作定义为一个虚函数并放在模板函数框架中。以后只要在客户端调用模板函数,通过子类(如BMW)的重写GetPrice改变要输出的价格就完成复用了。
例如我们要打印“BMW车的价格为600000,我们需要提取重复的代码,如“车的价格”,然后只要把价格在子类中重新改写即可了。
角色:
1.AbstractClass(抽象类):在抽象类中定义了一系列基本操作,这些可以是具体的,也可以是抽象的,每一个基本操作对应算法的一个步骤,在其子类中可以重定义或实现这些步骤。同时,在抽象类中实现了一个模板方法(Template Method),用于定义一个算法的框架,模板方法不仅可以调用在抽象类中实现的基本方法,也可以调用在抽象类的子类中实现的基本方法,还可以调用其他对象中的方法。
2.ConcreteClass(具体子类):它是抽象类的子类,用于实现在父类中声明的抽象基本操作以完成子类特定算法的步骤,也可以覆盖在父类中已经实现的具体基本操作,它可以是多个的。
UML图:
代码:
#include <iostream>
#include <string>
using namespace std;
class Car
{
public:
string m_sCarName;
public:
~Car()
{
cout<<"调用析构函数!"<<endl;
}
virtual void SetName(string sName)
{
m_sCarName = sName;
}
virtual float GetPrice()
{
return 1;
}
void PrintCarPrice()
{
cout<<m_sCarName<<"车的价格为:"<<GetPrice()<<endl;
}
};
class BMW:public Car
{
public:
float GetPrice()
{
return 600000;
}
};
class Ferrali:public Car
{
public:
float GetPrice()
{
return 1100000;
}
};
class Benz:public Car
{
public:
float GetPrice()
{
return 800000;
}
};
int main()
{
int iSeq=0;
Car* pCar = new Car;
cout<<"请选择您想知道车的价格:"<<endl;
cout<<"BMW:1;Ferrali:2;Benz:3"<<endl;
cin>>iSeq;
switch (iSeq)
{
case 1:
pCar = new BMW;
pCar->SetName("BMW");
break;
case 2:
pCar = new Ferrali;
pCar->SetName("Ferrali");
break;
case 3:
pCar = new Benz;
pCar->SetName("Benz");
break;
default:
pCar->SetName("Car");
break;
}
pCar->PrintCarPrice();
delete pCar;
pCar = NULL;
return 1;
}
发散:
我们知道实现C++的多态有三种方法:函数重载,模板函数和虚函数。虚函数实现的多态称为动态多态,上面代码有以下特点:
1.子类的对象转换给父类的对象,我们称为向上转型。它是安全的,自动完成,并且会丢失子类型的信息;
2.为了解决子类型信息丢失的问题(子类对象转换给父类),父类必须实现了一个虚函数;
3.子类有完全相同的函数,覆盖重写父类的虚函数,这样便能实现动态多态了(否则只能用指针或引用了)。
总结:
1.模板方法模式是通过把不变的行为搬移到父类中,去除子类中的重复代码;
2.模板方法模式提供了一个很好的代码复用平台,我们的目的是:消除重复,提倡易用和简洁,增强代码复用性。