在方法中定义算法的框架,将某些步骤推迟到子类。模板方法(
Template Method)可让子类在不更改算法结构的情况下重新定义算法的某些步骤。
管理公司员工的日常行程可能是一项耗时的工作。如果可以使用程序将日常任务编程为自动发生,那将容易得多。Mark在Yahaa Inc工作了四年, 他是一名程序员,他的日常工作主要的是从事与编程有关的任务。Elisa是同一家公司的营销经理;像Mark一样,她有自己的日常活动,而她则主要从事营销工作。
作为程序员,Mark在公司的日常工作如下:
class Programmer
{
public function workRoutine()
{
$this->markAttendance();
$this->doProgrammingTask();
$this->reportDailyCompletion();
}
public function markAttendance()
{
echo '我正在打卡';
}
public function doProgrammingTask()
{
echo '正在做编程的任务';
}
public function reportDailyCompletion()
{
echo '我正在报告我的每日完成进度';
}
}
markAttendance())。doingProgrammingTask())reportDailyCompletion())现在,营销经理Elisa的行事方式与Mark几乎相同,除了第二步。作为营销人员,日常工作的第二部分是执行与营销相关的任务。
我们可以轻松地在上面的两个类中发现代码重复。程序员和营销人员都共享一些通用程序。
我们如何来重构代码呢?
如果可以在超类中定义一些通用的方法,但仍然给子类提供灵活地可以定义子类自身的功能,那么显然可以做得更好。而这就需要应用到模板方法(Template Method)模式了。
现在我们用一些预定义的函数定义一个抽象的超类:
class Employee
{
public function workRoutine()
{
$this->markAttendance();
$this->doWork();
$this->reportDailyCompletion();
}
public function markAttendance()
{
echo 'I am marking my attendance';
}
public function reportDailyCompletion()
{
echo 'I am reporting my daily completion';
}
abstract public function doWork();
}
该类看起来与之前的Programmer类非常相似,不同之处在于,我们删除了两个类之间不同的函数,并用抽象类doWork()代替了它。
现在,让我们重构Programmer和并且可以很方便的创建针对营销人员Marketer类:
class Programmer extends Employee
{
public function doWork()
{
$this->doProgrammingTask();
}
public function doProgrammingTask()
{
echo 'doing programming task';
}
}
class Marketer extends Employee
{
public function doWork()
{
$this->doMarketingTask();
}
public function doMarketingTask()
{
echo 'doing marketing task';
}
}
如我们所见,Programmer和Marketer类都变得更加整洁,不再有任何代码重复。
在我们的示例中,我们在方法(Employee类中的workRoutine()方法)中定义算法的框架,将某些步骤(doWork())推迟到子类(Programmer和Marketer类)中。模板方法(Employee类中的doWork()方法)使子类(Programer和Marketer类)重新定义算法的某些步骤(doWork()),而无需更改算法的结构。