Много лесен и приятен design pattern. И наистина си заслужава името.
Цялата му идея се състои в това в един абсклас (но може и не абстрактен), ще го наричаме „base class“, да имаме един или повече final методи (важно е да не могат да се овъррайдват), който/които ще са т.н. „темплейти“, тоест, подобно на HTML темплейт, те ще викат други методи и ще сглобяват нещо цялостно.
В абскласа също трябва да има един или повече абстрактни методи, който да се дефинират в класовете наследници. Ще ги наричаме „hook methods“, защото на тях ще „закачаме“ подобно на куки, какво трябва да правят по-късно.
Но също и те (тези, абстрактните методи) да бъдат викани и в „темплейт метода“. В който темплейт метод може да има и друга логика разбира се, могат да се викат и други методи… Може и да не се викат всички от тези абстрактните (the hooks), може да се викат в различен ред, по колкото пъти трябва и т.н…
Идеята е те (hooks) да бъдат дефинирани в класовете наследници, за да може като инстанцираме някой от наследниците и извикаме темплейт метода от абскласа (родителя), той да може в себе си да ги извика тях (hooks) и така подобно на темплейт, да сглоби цялата логика, използвайки ги така да се каже, за да „попълни“ себе си с тях.
Отделните „парчета“ ще варират според как са дедфинирани в класа/класовете наследници, но схемата по-която се викат е една и е зададена в метода-темплейт.
Ето един крайно опростен пример:
<?php abstract class PatapanAbstract { final public function templateMeto1(): void { // some other logic or methods calls... $this->someSimpleMeto1(); // some other logic or methods calls... $this->absMeto1(); // some other logic or methods calls... $this->someSimpleMeto2(); $this->absMeto2(); // some other logic or methods calls... $this->someSimpleMeto2(); } private function someSimpleMeto1(): void { echo 'Hello, this is private simple meto 1'; } private function someSimpleMeto2(): void { echo 'Hello, this is private simple meto 2'; } abstract protected function absMeto1(); abstract protected function absMeto2(); } class PatapanConcrete1 extends PatapanAbstract { public function absMeto1(): void { echo 'This is meto 1'; } public function absMeto2(): void { echo 'This is meto 2'; } } $p1 = new PatapanConcrete1; $p1->templateMeto1();
Ще имаме резултат:
Hello, this is private simple meto 1 Hello, this is meto 1 Hello, this is private simple meto 2 Hello, this is meto 2 Hello, this is private simple meto 2
Вижда се ясно как в „PatapanAbstract“ е създаден нещо като темплейт, а какво да има в отделните „парчета“, се дефинира в класа наследник/наследници.
The template method is a method in a superclass, usually an abstract superclass, and defines the skeleton of an operation in terms of a number of high-level steps. These steps are themselves implemented by additional helper methods in the same class as the template method.
Отделно, може и отделните hook методи да не са абстрактни, тоест да не е задължително да ги дефинираме в класовете-наследници. Може да са обикновени празни методи.
The helper methods may be either abstract methods, in which case subclasses are required to provide concrete implementations, or hook methods, which have empty bodies in the superclass. Subclasses can (but are not required to) customize the operation by overriding the hook methods. The intent of the template method is to define the overall structure of the operation, while allowing subclasses to refine, or redefine, certain steps.
И друго много съществено за този design pattern e, че логиката в темплейт метода е твърдо зададена и не може да се променя в наследниците. Затова и темплейт метода трябва да е задължително final.
Динамична е логиката по отделните „парчета“ – the hooks.
Също, понеже главният клас (base class) се явява „high-level module“ за наследяващите го „low-lewel“ модули, и не зависи от тях както и ги оставя те да задават своята логика, можем да кажем, че Template method design pattern е пример за „Inversion of control principle“.