模板模式就是定义一个操作中的算法的骨架,而将步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义算法的某些特定步骤。但调用将以抽象类中定义的方式进行。
两个角色:
抽象类(AbstractClass):实现了模板方法,定义了算法的骨架。
具体类(ConcreteClass):实现抽象类中的抽象方法,已完成完整的算法。
主要解决:一些方法通用,却在每一个子类都重新写了这一方法。
何时使用:有一些通用的方法。
如何解决:将这些通用算法抽象出来。
关键代码:在抽象类实现,其他步骤在子类实现。
应用实例:1、在造房子的时候,地基、走线、水管都一样,只有在建筑的后期才有加壁橱加栅栏等差异。2、西游记里面菩萨定好的 81 难,这就是一个顶层的逻辑骨架。
优点:1、封装不变部分,扩展可变部分。2、提取公共代码,便于维护。3、行为由父类控制,子类实现。
缺点:每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。
使用场景:1、有多个子类共有的方法,且逻辑相同。2、重要的、复杂的方法,可以考虑作为模板方法。
注意事项:为防止恶意操作,一般模板方法都加上 final 关键词。
考虑一个计算存款利息的例子。假设系统需要支持两种存款账号,即货币市场(Money Market)账号和定期存款(Certificate of Deposite)账号。这两种账号的存款利息是不同的,因此,在计算一个存户的存款利息额时,必须区分两种不同的账号类型。
<?php
//抽象模板
abstract class Account{
//模板方法,给出了逻辑的骨架,而逻辑的组成是一些相应的抽象操作,它们推迟到子类去实现。
function CalculateInterest()
{
$Money = $this->GetMoney();
$InterestRate = $this->GetInterestRate();
echo "The Interest is ".$Money*$InterestRate;
}
//一些抽象行为,放到子类去实现
public abstract function GetMoney();
public abstract function GetInterestRate();
}
//具体模板角色类
//普通帐号
class MoneyMarket extends Account{
private $Money;
function __construct($Money)
{
$this->Money = $Money;
}
function GetMoney()
{
return $this->Money;
}
function GetInterestRate()
{
return 0.045;
}
}
//定期帐号
class CDAccount extends Account{
private $Money;
function __construct($Money)
{
$this->Money = $Money;
}
function GetMoney()
{
return $this->Money;
}
function GetInterestRate()
{
return 0.06;
}
}
//调用
//普通帐号
$MoneyMarket = new MoneyMarket(2000000);
$MoneyMarket->CalculateInterest();
//定期帐号
$CDAccount = new CDAccount(2000000);
$CDAccount->CalculateInterest();
?>