Итак, я изучаю шаблоны проектирования, и я изучаю метод шаблонов.
Из того, как я это понял, это набор методов (скелет), обернутый в метод (операцию) над абстрактным классом (если выполняется через наследие), где разные конкретные подклассы пишут свою собственную реализацию этих методов (не все они).
Но я сомневаюсь, что произойдет, если некоторые, может быть, 2 метода скелета не будут использоваться определенным конкрецией? Вот мой пример, который я сделал, который полностью нарушает SRP:
using System;
namespace TemplatePattern
{
public abstract class Coffee
{
public void MakeCoffee()
{
HeatWater();
PutCoffee();
if (HaveMilk())
{
PutMilk();
}
if (HaveGratedChocolate())
{
PutGratedChocolate();
}
PutSweetener();
ServeCoffee();
}
internal void HeatWater()
{
Console.WriteLine($"I heated the water");
}
internal void ServeCoffee()
{
Console.WriteLine($"Coffee Served");
}
internal void PutCoffee()
{
Console.WriteLine("I put 2 spoons of Coffee");
}
internal virtual void PutMilk() { }
internal virtual void PutGratedChocolate() { }
internal abstract void PutSweetener();
public virtual bool HaveMilk()
{
return false;
}
public virtual bool HaveGratedChocolate()
{
return false;
}
}
}
Конкретный класс SimpleCoffeeWithMilk:
using System;
namespace TemplatePattern
{
public class SimpleCoffeWithMilk : Coffee
{
public override bool HaveMilk()
{
return true;
}
internal override void PutSweetener()
{
Console.WriteLine($"I put 1 spoon of Sugar");
}
internal override void PutMilk()
{
Console.WriteLine($"I put 100Cc of Milk");
}
}
}
Другой класс бетона:
using System;
namespace TemplatePattern
{
public class CoffeeWithChocolate : Coffee
{
public override bool HaveGratedChocolate()
{
return true;
}
internal override void PutGratedChocolate()
{
Console.WriteLine("Put Chocolate");
}
internal override void PutSweetener()
{
Console.WriteLine($"Put Sugar");
}
}
}
Главная точка входа:
using System;
namespace TemplatePattern
{
class Program
{
static void Main(string[] args)
{
SimpleCoffeWithMilk coffeWithMilk = new SimpleCoffeWithMilk();
CoffeeWithChocolate coffeeWithChocolate = new CoffeeWithChocolate();
coffeWithMilk.MakeCoffee();
Console.WriteLine("\n\n");
coffeeWithChocolate.MakeCoffee();
Console.ReadLine();
}
}
}
Идея состоит в том, чтобы избавиться от этих операторов If, есть ли способ сделать это с помощью метода шаблона, когда некоторые методы выполняются в зависимости от конкретного класса?
Я думал о создании интерфейсов, таких как ICoffeeWithMilk
с методом PutMilk()
, и реализации этого интерфейса в моем конкретном классе SimpleCoffeeWithMilk
, но, наблюдая UML, метод Template для того, что я видел, не полагается на интерфейсы.
Редактировать: Теперь, когда я об этом думаю, я не могу использовать интерфейс, так как метод шаблона относится к набору упорядоченных методов в операции, поэтому эти методы не работают.
Edit 2: Хорошо, я думал, что PutMilk()
и PutGratedChocolate()
являются методами Hook, возможно, я могу сделать их абстрактными методами и в конкретные классы не помещать какую-либо реализацию, даже не реализован класс исключений. При этом они могут существовать без каких-либо утверждений в моем методе шаблона. Но я думаю, я не уверен, что это нарушает принцип замещения Лискова.
Редактировать 3: Хорошо ... Я снова подумал и пришел к выводу, что, если эти методы являются виртуальными и не имеют реализации в абстрактном классе, мне не следует беспокоиться о том, чтобы спросить Если конкретный класс использует этот метод, то вы пишете алгоритм, если вы его не используете, то не выполняете, и он ничего не будет делать, он перейдет к следующему шагу.