Шаблонный метод — это поведенческий паттерн, задающий скелет алгоритма в суперклассе и заставляющий подклассы реализовать конкретные шаги этого алгоритма.
Сложность:
Популярность:
Применимость: Шаблонные методы можно встретить во многих библиотечных классах C#. Разработчики создают их, чтобы позволить клиентам легко и быстро расширять стандартный код при помощи наследования.
Признаки применения паттерна: Класс заставляет своих потомков реализовать методы-шаги, но самостоятельно реализует структуру алгоритма.
Концептуальный пример
Этот пример показывает структуру паттерна Шаблонный метод , а именно — из каких классов он состоит, какие роли эти классы выполняют и как они взаимодействуют друг с другом.
Program.cs: Пример структуры паттерна
using System;
namespace RefactoringGuru.DesignPatterns.TemplateMethod.Conceptual
{
// Абстрактный Класс определяет шаблонный метод, содержащий скелет
// некоторого алгоритма, состоящего из вызовов (обычно) абстрактных
// примитивных операций.
//
// Конкретные подклассы должны реализовать эти операции, но оставить сам
// шаблонный метод без изменений.
abstract class AbstractClass
{
// Шаблонный метод определяет скелет алгоритма.
public void TemplateMethod()
{
this.BaseOperation1();
this.RequiredOperations1();
this.BaseOperation2();
this.Hook1();
this.RequiredOperation2();
this.BaseOperation3();
this.Hook2();
}
// Эти операции уже имеют реализации.
protected void BaseOperation1()
{
Console.WriteLine("AbstractClass says: I am doing the bulk of the work");
}
protected void BaseOperation2()
{
Console.WriteLine("AbstractClass says: But I let subclasses override some operations");
}
protected void BaseOperation3()
{
Console.WriteLine("AbstractClass says: But I am doing the bulk of the work anyway");
}
// А эти операции должны быть реализованы в подклассах.
protected abstract void RequiredOperations1();
protected abstract void RequiredOperation2();
// Это «хуки». Подклассы могут переопределять их, но это не обязательно,
// поскольку у хуков уже есть стандартная (но пустая) реализация. Хуки
// предоставляют дополнительные точки расширения в некоторых критических
// местах алгоритма.
protected virtual void Hook1() { }
protected virtual void Hook2() { }
}
// Конкретные классы должны реализовать все абстрактные операции базового
// класса. Они также могут переопределить некоторые операции с реализацией
// по умолчанию.
class ConcreteClass1 : AbstractClass
{
protected override void RequiredOperations1()
{
Console.WriteLine("ConcreteClass1 says: Implemented Operation1");
}
protected override void RequiredOperation2()
{
Console.WriteLine("ConcreteClass1 says: Implemented Operation2");
}
}
// Обычно конкретные классы переопределяют только часть операций базового
// класса.
class ConcreteClass2 : AbstractClass
{
protected override void RequiredOperations1()
{
Console.WriteLine("ConcreteClass2 says: Implemented Operation1");
}
protected override void RequiredOperation2()
{
Console.WriteLine("ConcreteClass2 says: Implemented Operation2");
}
protected override void Hook1()
{
Console.WriteLine("ConcreteClass2 says: Overridden Hook1");
}
}
class Client
{
// Клиентский код вызывает шаблонный метод для выполнения алгоритма.
// Клиентский код не должен знать конкретный класс объекта, с которым
// работает, при условии, что он работает с объектами через интерфейс их
// базового класса.
public static void ClientCode(AbstractClass abstractClass)
{
// ...
abstractClass.TemplateMethod();
// ...
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Same client code can work with different subclasses:");
Client.ClientCode(new ConcreteClass1());
Console.Write("\n");
Console.WriteLine("Same client code can work with different subclasses:");
Client.ClientCode(new ConcreteClass2());
}
}
}
Output.txt: Результат выполнения
Same client code can work with different subclasses:
AbstractClass says: I am doing the bulk of the work
ConcreteClass1 says: Implemented Operation1
AbstractClass says: But I let subclasses override some operations
ConcreteClass1 says: Implemented Operation2
AbstractClass says: But I am doing the bulk of the work anyway
Same client code can work with different subclasses:
AbstractClass says: I am doing the bulk of the work
ConcreteClass2 says: Implemented Operation1
AbstractClass says: But I let subclasses override some operations
ConcreteClass2 says: Overridden Hook1
ConcreteClass2 says: Implemented Operation2
AbstractClass says: But I am doing the bulk of the work anyway
Шаблонный метод на других языках программирования