在现实生活中,我们做的大多数树事情都包含了好几个步骤。比如我从学校回家,需要下面几个步骤,宿舍->学校门口->市里车站->县里车站->我家,这些步骤有着固定的次序,一些步骤是固定的,但是有些步骤存在着变化的部分,例如从宿舍到学校门口,我每次采用走的方式,这个步骤是固定不变的,然后我要从学校门口到车站,此时我可以坐公交车,或者打的;下一个步骤从市里的车站到我们县里的车站,我可以做公共汽车或者火车,最后一个步骤我要从县里的车站回到我家,如果是在白天,我可以坐公交车回家,如果晚上没车,我可以打车或者让我爸开车接我回家。
在软件开发中我们也经常会遇到类似的情况,我们为了实现一个功能采用了很多的步骤,这些步骤有固定的部分,也有变化的部分。此时,我们就可以采用模板方法模式来解决这一类问题。
模板方法模式定义了一个操作中的算法骨架,而将一些步骤延迟到子类中实现,模板方法使得子类可以不改变一个算法的结构就可以重定义该算法的某些特定步骤。
模板方法中包含两个角色:
1.AbstractClass(抽象类):抽象类中定义了一系列基本操作,这些操作可以是具体的,也可以是抽象的,子类可以重定义或者实现这些操作。抽象类中同时也定义了一个模板方法,这个方法定义了算法的框架。
2.ConcreteClass(具体子类):是抽象类的子类,实现了父类中的声明的抽象基本操作,或者覆盖了父类中的具体操作。
模板方法的UML图如下:
利用模板方法模式实现我上面举的例子:
class GoingHome
{
public:
virtual ~GoingHome(){}
void goHome()
{
dormitory2SchoolGate();
schoolGate2CityStation();
cityStation2CountyStation();
countyStation2Home();
}
void dormitory2SchoolGate() //从宿舍到校门口,固定不变的步骤,直接在抽象类中定义为具体方法
{
cout << "宿舍去校门口,总是走路" << endl;
}
virtual void schoolGate2CityStation() = 0; //从校门口到市里车站,抽象方法,子类实现
virtual void cityStation2CountyStation() = 0; //从市里车站到县里车站,抽象方法,子类实现
virtual void countyStation2Home() = 0; //从县里车站到市里车站,抽象方法,子类实现
};
class GoingHomeWay1 :public GoingHome //子类,实现操作中的变化部分
{
public:
~GoingHomeWay1(){}
void schoolGate2CityStation()
{
cout << "学校到市里车站,坐公交" << endl;
}
void cityStation2CountyStation()
{
cout << "市里车站到县里车站,坐火车" << endl;
}
void countyStation2Home()
{
cout << "县里车站到家,打的" << endl;
}
};
int main()
{
GoingHome* gh = new GoingHomeWay1();
gh->goHome();
return 0;
}