在方法中定义算法的框架,将某些步骤推迟到子类。模板方法(
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()
),而无需更改算法的结构。