Шаблонний метод описується як «поведінковий шаблон проектування, що визначає основу алгоритму і дозволяє нащадкам перевизначати деякі кроки алгоритму, не змінюючи його структуру в цілому».
Метою є розділення змінюваного і незмінюваного коду, зберігаючи проблеми ізольованими у спеціальних класах. Такі підкласи реалізують потім усі конкретні кроки.
Огляньте наведену схему, що ілюструє структуру Шаблонного метода:
Покажіть мені код
Припустимо, що ми все ще створюємо застосунок, який буде формувати звіти про кількість годин, які пропрацював кожен робітник.
Реалізація класу Report
досить проста:
class Report
def generate_report!
get_employees_worked_time
format_report
send_to_stakeholders
end
def get_employees_worked_time
# Отримуємо цю інформацію з бази даних
end
def format_report
# Генерація HTML, що містить розмітку звіту
end
def send_to_stakeholders
# Виклик сервісу send email
end
end
Код працює відмінно. Але якщо нам необхідно буде згенерувати такий самий звіт у текстовому форматі? Єдина частина, що змінюватиметься — крок формування звіту. Саме в такому випадку гарним рішенням буде застосувати Шаблонний метод.
Для застосування цього шаблону, ми перетворимо клас Report
на абстрактний клас, що може наслідуватись від декількох конкретних класів.
Повернемось до нашого коду. Єдиною необхідною зміною буде залишити реалізацію методу format_report
на дочірній клас:
class ReportTemplate
def generate_report!
get_employees_worked_time
format_report
send_to_stakeholders
end
def get_employees_worked_time
# Отримуємо цю інформацію з бази даних
end
def format_report
raise NotImplementedError
end
def send_to_stakeholders
# Виклик сервісу send email
end
end
І для кожної варіації звіту нам необхідно буде створити конкретний підклас:
class HTMLReport < ReportTemplate
def format_report
# реалізує звіт у форматі HTML
end
end
class TextReport < ReportTemplate
def format_report
# реалізує звіт у текстовому форматі
end
end
Якщо нам колись необхідно буде створити новий формат, ми лише створимо новий конкретний клас. Таким чином, отримуємо чудовий приклад принципу відкритості/закритості. Організувавши наш код таким чином, ми зможемо безпечніше та простіше застосовувати будь-які зміни у майбутньому.
Висновок
Якщо вам треба змінити лише кілька методів або зробити їх опціональними, цей шаблон — ідеальне рішення. Шаблонний клас реалізує скелет, а підкласи — деталі реалізації так, як це необхідно.
Ще немає коментарів