一、模板方法模式的定义
模板方法是在一个算法中定义一个算法的骨架,具体的实现延迟到子类中去实现。模式方式可以使得子类在不改变算法结构的情况下,重新定义算法某些步骤的实现。
看到 “设计模式” 我们往往感觉高深莫测,其实模板方法模式非常之简单,我们只需要关心一个方法而已。
二、模板方法的使用场景
当算法的实现的骨架或者步骤是相对固定的,而其中某些实现方法的步骤是不一样的时候,就可以使用模板方法模式。
-
多个子类有共同的方法,并且逻辑基本上相同。
-
重要复杂、核心的方法可以设计为模板方法,周边的相关的细节功能可以由子类去实现。
-
重构代码的时候,可以把相同的逻辑代码抽取出来。
举个栗子:
一个游戏支付系统,有多种支付的方式,包括支付宝,微信支付等等方式,它们支付成功回调通知系统时,一般都会经历几个阶段,接受参数,验证签名,划账,通知游戏发货,修改订单的状态,这些步骤就是相对固定的,设计成一个模板方法,让子类去继承这个方法,而其中有些步骤的实现方式会有所不同,比如接收参数的形式,微信支付使用xml格式传输数据,而支付宝书数组格式,同时验证签名的过程也有所不同,接收参数和验证签名等方法的具体实现我们就可以延迟要子类中实现。
三、模板方法的具体实现
步骤一、创建抽象类和模板方法
abstract class Cook
{
//定义成final方法,子类可以继承,防止子类修改该算法的步骤或者骨架
final public function cookProcess()
{
//1、倒油
$this->pourOil();
//2、热油
$this->heatOil();
//3、倒蔬菜,由于每个菜是不一样的,所以需要子类去实现
$this->pourVegetable();
//4、放入调味品 每个菜的调味品也是不一样的,延迟到子类中实现
$this->pourSauce();
//5、翻炒
$this->fry();
}
private function pourOil()
{
echo "开始倒油" . PHP_EOL;
}
private function fry()
{
echo "翻炒" . PHP_EOL;
}
private function heatOil()
{
echo "热油" . PHP_EOL;
}
abstract function pourSauce();
abstract function pourVegetable();
}
步骤二、创建子类继承抽象类,并且实现抽象方法
/**
* Class cookeBaoCai
* 手撕包菜
*/
class cookeBaoCai extends Cook
{
public function pourSauce()
{
echo '放入辣椒' . PHP_EOL;
}
public function pourVegetable()
{
echo "放入包菜" . PHP_EOL;
}
}
/**
* Class cookCaixin
* 蒜蓉菜心
*/
class cookCaixin extends Cook
{
public function pourVegetable()
{
echo "放入菜心" . PHP_EOL;
}
public function pourSauce()
{
echo "放入蒜蓉" . PHP_EOL;
}
}
步骤三、客户端进行调用
/**
* 客户端开始调用
*/
$cookCaixin = new cookCaixin();
$cookCaixin->cookProcess();
$cookBaocai = new cookeBaoCai();
$cookBaocai->cookProcess();
最终结果
开始倒油
热油
放入菜心
放入蒜蓉
翻炒
开始倒油
热油
放入包菜
放入辣椒
翻炒
四、模板方法的优缺点
优点如下:
- 封装不变的部分,扩展可变的部分,把认为不变的部分封装到父类,可变的部分通过继承来实现扩展
- 提取公共的代码,便于维护
- 行为由父类控制,子类实现
缺点如下:
- 需要修改算法的骨架时,需要修改抽象类。因为行为由父类控制,子类实现,增加了代码阅读的复杂度,同时由于引入了抽象类,会引入很多的子类,加大了系统的复杂度。