【发布时间】:2018-12-06 01:31:21
【问题描述】:
所以,我学习设计模式,学习模板方法。
根据我的理解,它是一组方法(骨架)包装在抽象类(如果通过遗产完成)上的方法(操作)中,不同的具体子类在其中编写自己的这些方法的实现(不是全部)。
但是我有一个疑问,如果某些具体的骨骼没有使用骨骼的一些,也许是 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,我看到的模板方法不依赖于接口。
编辑:现在想来,不能用接口,因为模板方法在操作中涉及到一组有序的方法,所以这些方法在操作之外。
编辑 2: 好的,我在想 PutMilk() 和 PutGratedChocolate() 是 Hook 方法,也许我可以将它们设为抽象方法,并且在具体类中不要放置任何实现,甚至没有未实现异常类。有了这个,它们可以在我的模板方法中没有任何 if 语句的情况下存在。但我认为,我不确定这是否违反了 Liskov 替换原则。
编辑 3: 嗯……我又在想,得出的结论是,如果这些方法是虚拟的并且在抽象类上没有实现,我不应该担心问,如果具体类使用那个方法,那么你写算法,如果你不使用,那就不要,它什么也不做,它会进入下一步。
【问题讨论】:
标签: c# design-patterns template-method-pattern