Шаблонний метод на C#
Шаблонний метод — це поведінковий патерн, який визначає кістяк алгоритму в суперкласі та змушує підкласи реалізувати конкретні кроки цього алгоритму.
Складність:
Популярність:
Застосування: Шаблонні методи можна зустріти в багатьох бібліотечних класах C#. Розробники створюють їх, щоб дозволити клієнтам легко та швидко розширювати стандартний код за допомогою спадкування.
Ознаки застосування патерна: Клас змушує своїх нащадків реалізувати методи-кроки, але самостійно реалізовує структуру алгоритму.
Концептуальний приклад
Цей приклад показує структуру патерна Шаблонний метод, а саме — з яких класів він складається, які ролі ці класи виконують і як вони взаємодіють один з одним.
Program.cs: Приклад структури патерна
using System; namespace RefactoringGuru.DesignPatterns.TemplateMethod.Conceptual { // The Abstract Class defines a template method that contains a skeleton of // some algorithm, composed of calls to (usually) abstract primitive // operations. // // Concrete subclasses should implement these operations, but leave the // template method itself intact. abstract class AbstractClass { // The template method defines the skeleton of an algorithm. public void TemplateMethod() { this.BaseOperation1(); this.RequiredOperations1(); this.BaseOperation2(); this.Hook1(); this.RequiredOperation2(); this.BaseOperation3(); this.Hook2(); } // These operations already have implementations. 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"); } // These operations have to be implemented in subclasses. protected abstract void RequiredOperations1(); protected abstract void RequiredOperation2(); // These are "hooks." Subclasses may override them, but it's not // mandatory since the hooks already have default (but empty) // implementation. Hooks provide additional extension points in some // crucial places of the algorithm. protected virtual void Hook1() { } protected virtual void Hook2() { } } // Concrete classes have to implement all abstract operations of the base // class. They can also override some operations with a default // implementation. class ConcreteClass1 : AbstractClass { protected override void RequiredOperations1() { Console.WriteLine("ConcreteClass1 says: Implemented Operation1"); } protected override void RequiredOperation2() { Console.WriteLine("ConcreteClass1 says: Implemented Operation2"); } } // Usually, concrete classes override only a fraction of base class' // operations. 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 { // The client code calls the template method to execute the algorithm. // Client code does not have to know the concrete class of an object it // works with, as long as it works with objects through the interface of // their base class. 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