设计模式系列漫谈之六 - 模板方法模式
在 设计模式系列漫谈之五 - 迭代器模式 中, 调用代码如下:
IListIterator iterator=new BoyList();
iterator.AddBoy(new BoyA);
iterator.AddBoy(new BoyB);
while (iterator.MoveNext())
{
IBoy boy=(IBoy)iterator.Current
if (boy.GetAge()<30 || boy.GetAge()>35)
{
iterator.RemoveBoy(boy);
}
else if (boy.GetHeight()<180)
{
iterator.RemoveBoy(boy);
}
else if (!boy.HasHouse())
{
iterator.RemoveBoy(boy);
}
else if (!boy.HasCar())
{
iterator.RemoveBoy(boy);
}
else if (!boy.HasMillion())
{
iterator.RemoveBoy(boy);
}
else
{
Console.WriteLine(boy.Name);
}
}
iterator.AddBoy(new BoyA);
iterator.AddBoy(new BoyB);
while (iterator.MoveNext())
{
IBoy boy=(IBoy)iterator.Current
if (boy.GetAge()<30 || boy.GetAge()>35)
{
iterator.RemoveBoy(boy);
}
else if (boy.GetHeight()<180)
{
iterator.RemoveBoy(boy);
}
else if (!boy.HasHouse())
{
iterator.RemoveBoy(boy);
}
else if (!boy.HasCar())
{
iterator.RemoveBoy(boy);
}
else if (!boy.HasMillion())
{
iterator.RemoveBoy(boy);
}
else
{
Console.WriteLine(boy.Name);
}
}
看到上面一大串IF...ELSE,相信大家一定会觉得非常不爽。这很显然是设计模式的大忌。其实我们可以通过模板方法模式来改进一下。
模板方法(Template Method)模式的解决方案
准备一个抽象类,将部分逻辑以具体方法以及具体构造子类的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。模板方法定义两个角色:
抽象模版(AbstractClass)角色:定义了一个或多个抽象方法,具体操作由子类(具体模版)实现。然后,定义一个模版方法,并且实现这个模版方法,其逻辑的组成步骤就是之前定义的抽象操作。抽象模板必须是一个抽象类。
具体模版(ConcreteClass)角色有如下的责任:实现父类所定义的一个或多个抽象方法。
抽象模板如下:
namespace XiaoXue
{
public abstract AbstractBoy
{
public string Name;
public abstract int GetAge();
public abstract int GetHeight();
public abstract bool HasHouse();
public abstract bool HasCar();
public abstract bool HasMillion();
public bool TemplateMethod() //抽象方法
{
bool blAge=boy.GetAge()>30 && boy.GetAge()<35;
bool blHeight=boy.GetHeight()>180;
bool blHouse=boy.HasHouse();
bool blCar=boy.HasCar();
bool blMillion=boy.HasMillion();
return blAge && blHeight && blHouse && blCar && blMillion;
}
}
}
{
public abstract AbstractBoy
{
public string Name;
public abstract int GetAge();
public abstract int GetHeight();
public abstract bool HasHouse();
public abstract bool HasCar();
public abstract bool HasMillion();
public bool TemplateMethod() //抽象方法
{
bool blAge=boy.GetAge()>30 && boy.GetAge()<35;
bool blHeight=boy.GetHeight()>180;
bool blHouse=boy.HasHouse();
bool blCar=boy.HasCar();
bool blMillion=boy.HasMillion();
return blAge && blHeight && blHouse && blCar && blMillion;
}
}
}
子对象具体类如下:
namespace XiaoXue
{
public class BoyA : AbstractBoy
{
public BoyA(string name)
{
base.Name=name;
}
public override int GetAge()
{
return 25;
}
public override int GetHeight()
{
return 187;
}
public override bool HasHouse()
{
return true;
}
public override bool HasCar()
{
return false;
}
public override bool HasMillion()
{
return false;
}
}
public class BoyB : AbstractBoy
{
public BoyB(string name)
{
base.Name=name;
}
public override int GetAge()
{
return 32;
}
public override int GetHeight()
{
return 170;
}
public override bool HasHouse()
{
return true;
}
public override bool HasCar()
{
return true;
}
public override bool HasMillion()
{
return true;
}
}
}
{
public class BoyA : AbstractBoy
{
public BoyA(string name)
{
base.Name=name;
}
public override int GetAge()
{
return 25;
}
public override int GetHeight()
{
return 187;
}
public override bool HasHouse()
{
return true;
}
public override bool HasCar()
{
return false;
}
public override bool HasMillion()
{
return false;
}
}
public class BoyB : AbstractBoy
{
public BoyB(string name)
{
base.Name=name;
}
public override int GetAge()
{
return 32;
}
public override int GetHeight()
{
return 170;
}
public override bool HasHouse()
{
return true;
}
public override bool HasCar()
{
return true;
}
public override bool HasMillion()
{
return true;
}
}
}
迭代器接口和迭代器不变,请见 设计模式系列漫谈之五 - 迭代器模式
调用代码如下:
IListIterator iterator=new BoyList();
iterator.AddBoy(new BoyA("张三"));
iterator.AddBoy(new BoyB("李四");
while (iterator.MoveNext())
{
AbstractBoy boy=(AbstractBoy )iterator.Current
if (!boy.TemplateMethod())
{
iterator.RemoveBoy(boy);
}
else
{
Console.WriteLine(boy.Name);
}
}
iterator.AddBoy(new BoyA("张三"));
iterator.AddBoy(new BoyB("李四");
while (iterator.MoveNext())
{
AbstractBoy boy=(AbstractBoy )iterator.Current
if (!boy.TemplateMethod())
{
iterator.RemoveBoy(boy);
}
else
{
Console.WriteLine(boy.Name);
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· [AI/GPT/综述] AI Agent的设计模式综述