基本概念
模板方法模式是一种行为设计模式, 它在超类(基类)中定义了一个算法的框架, 允许子类在不修改结构的情况下重写算法的特定步骤。
该模式是对于面向过程编程的一种抽象,它定义了一个算法的骨架 ,将一些步骤的实现延迟到子类 。子类在不改变算法结构的情况下,重新定义算法的某些步骤。
比如,做一道菜至少需要三步:
- 准备食材
- 烹饪
- 上菜
虽然不同菜品的烹饪方法和准备过程不同,但是不妨碍我们定义一个算法的"骨架",包含这三个步骤,然后将烹饪过程放到具体的炒菜类去实现,这样无论是吵什么才,都可以亚勇相同的炒菜算法,只需要在子类中实现具体的炒菜步骤就行。模板方法模式提高了代码的可复用性,类似于模板编程。
基本结构
在原来的若干类的基础上,抽象出一个模板方法,定义一个模板抽象类,然后具体类继承自模板类,实现了模板类中定义的抽象方法,去完成算法中的特定步骤。
- 模板类
AbstractClass
:由一个模板方法和若干个基本方法构成,模板方法定义了逻辑的骨架,按照顺序去调用包含的基本方法,基本方法同时是一些抽象方法,这些方法由子类去实现。基本方法还包含一些具体方法,他们是算法类的一部分但已经有默认实现,在具体子类可以继承或者重写。 - 具体类
ConcreteClass
:继承自模板类,实现了模板类中定义的抽象方法,完成算法中特定步骤的具体实现。
cpp
class AbstractClass {
/**
* The template method defines the skeleton of an algorithm.
*/
public:
void TemplateMethod() const {
this->BaseOperation1();
this->RequiredOperations1();
this->BaseOperation2();
this->Hook1();
this->RequiredOperation2();
this->BaseOperation3();
this->Hook2();
}
/**
* These operations already have implementations.
*/
protected:
void BaseOperation1() const {
std::cout << "AbstractClass says: I am doing the bulk of the work\n";
}
void BaseOperation2() const {
std::cout << "AbstractClass says: But I let subclasses override some operations\n";
}
void BaseOperation3() const {
std::cout << "AbstractClass says: But I am doing the bulk of the work anyway\n";
}
/**
* These operations have to be implemented in subclasses.
*/
virtual void RequiredOperations1() const = 0;
virtual void RequiredOperation2() const = 0;
/**
* These are "hooks." Subclasses may override them, but it's not mandatory
* since the hooks already have default (but empty) implementation. Hooks
* provide additional extension points in some crucial places of the
* algorithm.
*/
virtual void Hook1() const {}
virtual void Hook2() const {}
};
/**
* Concrete classes have to implement all abstract operations of the base class.
* They can also override some operations with a default implementation.
*/
class ConcreteClass1 : public AbstractClass {
protected:
void RequiredOperations1() const override {
std::cout << "ConcreteClass1 says: Implemented Operation1\n";
}
void RequiredOperation2() const override {
std::cout << "ConcreteClass1 says: Implemented Operation2\n";
}
};
/**
* Usually, concrete classes override only a fraction of base class' operations.
*/
class ConcreteClass2 : public AbstractClass {
protected:
void RequiredOperations1() const override {
std::cout << "ConcreteClass2 says: Implemented Operation1\n";
}
void RequiredOperation2() const override {
std::cout << "ConcreteClass2 says: Implemented Operation2\n";
}
void Hook1() const override {
std::cout << "ConcreteClass2 says: Overridden Hook1\n";
}
};
/**
* The client code calls the template method to execute the algorithm. Client
* code does not have to know the concrete class of an object it works with, as
* long as it works with objects through the interface of their base class.
*/
void ClientCode(AbstractClass *class_) {
// ...
class_->TemplateMethod();
// ...
}
int main() {
std::cout << "Same client code can work with different subclasses:\n";
ConcreteClass1 *concreteClass1 = new ConcreteClass1;
ClientCode(concreteClass1);
std::cout << "\n";
std::cout << "Same client code can work with different subclasses:\n";
ConcreteClass2 *concreteClass2 = new ConcreteClass2;
ClientCode(concreteClass2);
delete concreteClass1;
delete concreteClass2;
return 0;
}
Same client code can work with different subclasses:
AbstractClass says: I am doing the bulk of the work
ConcreteClass1 says: Implemented Operation1
AbstractClass says: But I let subclasses override some operations
ConcreteClass1 says: Implemented Operation2
AbstractClass says: But I am doing the bulk of the work anyway
Same client code can work with different subclasses:
AbstractClass says: I am doing the bulk of the work
ConcreteClass2 says: Implemented Operation1
AbstractClass says: But I let subclasses override some operations
ConcreteClass2 says: Overridden Hook1
ConcreteClass2 says: Implemented Operation2
AbstractClass says: But I am doing the bulk of the work anyway
上述代码源自该C++ 模板方法模式讲解和代码示例,我们来分析一下这个代码的含义。
首先是定义了一个抽象类,定义了公有方法TemplateMethod
,按照一定的顺序把所有的类方法都执行一遍。并提供了两个公有函数BaseOperation1
和BaseOperation2
,然后在保护域中定义了四个虚函数,RequireOperation1
和RequireOperation2
是纯虚函数,子类必须实现,还有两个Hook1
和Hook2
是提供了默认的空操作,子类可以选择自己实现。
然后在客户端直接去调用公有方法TemplateMethod
,不同的子类的实现方式略有区别,子类1只实现了必要的操作,而子类2还实现了Hook1
,即模板方法模式在已有的算法骨架下支持一定的拓展。
综上所述,模板方法模式适用于程式固化的模块,抽象出一个算法"骨架"这样可以方便统一管理,也支持一定的拓展。