模板模式
问题场景
咖啡和茶派生于抽象类饮料,咖啡和茶都具有烧水的方法,所以可以将烧水的方法提取到抽象类饮料中去实现,而咖啡具有一个向杯子加咖啡粉的方法,茶具有一个向杯子加茶叶的方法,看起来两个方法是不同的逻辑,而抽象类在很多地方都被其它类型所引用,也即其它类型都会调用抽象类而非其子类,以便解耦依赖。所以,我们应该尽量将看起来不一样但有共同点的行为提取到抽象类中定义成抽象成员,抽象成员就像模板,模板总是靠子类帮抽象类去填充实现,这样,在运行时,调用抽象实例就可以得到这些具体的实现了。
总结模式
将看起来具有不同逻辑但具有相同行为模式的成员泛化、提取到抽象类中定义为抽象成员,这样就统一了算法的命名,具体实现则交给各个子类去完成,从而使对抽象的引用变得更合理,使解耦和调用变得更具有可能性。
示例代码
public class Coffe
{
//烧水
public void BoilWater( ) { }
//冲泡咖啡
public void BrewingCoffe( ) { }
//倒入水杯
public void InCup( ) { }
//加牛奶
public void MilkInCup( ) { }
}
public class Tea
{
//烧水
public void BoilWater( ) { }
//冲泡茶叶
public void BrewingTea( ) { }
//倒入水杯
public void InCup( ) { }
//加柠檬
public void LemoInCup( ) { }
}
{
//烧水
public void BoilWater( ) { }
//冲泡咖啡
public void BrewingCoffe( ) { }
//倒入水杯
public void InCup( ) { }
//加牛奶
public void MilkInCup( ) { }
}
public class Tea
{
//烧水
public void BoilWater( ) { }
//冲泡茶叶
public void BrewingTea( ) { }
//倒入水杯
public void InCup( ) { }
//加柠檬
public void LemoInCup( ) { }
}
两个类中,都有烧水和倒入水杯的方法,应提取到抽象类中定义成实例方法
public class Drink
{
//烧水
public void BoilWater( ) { }
//倒入水杯
public void InCup( ) { }
}
{
//烧水
public void BoilWater( ) { }
//倒入水杯
public void InCup( ) { }
}
两个类中,冲泡的对象和附加的材料虽然不一样,但可以找到它们的共同点,那就是冲泡和附加材料,虽然具体实现的细节不一样,但还是可以将它们泛化为两个相同的行为。
public abstract class Drink
{
//烧水
public void BoilWater( ) { }
//倒入水杯
public void InCup( ) { }
//冲泡,抽象
public abstract void Brewing( );
//加材料,抽象
public abstract void XxInCup( );
}
public class Coffe : Drink
{
public override void Brewing( ) { }
public override void XxInCup( ) { }
}
public class Tea : Drink
{
public override void Brewing( ) { }
public override void XxInCup( ) { }
}
{
//烧水
public void BoilWater( ) { }
//倒入水杯
public void InCup( ) { }
//冲泡,抽象
public abstract void Brewing( );
//加材料,抽象
public abstract void XxInCup( );
}
public class Coffe : Drink
{
public override void Brewing( ) { }
public override void XxInCup( ) { }
}
public class Tea : Drink
{
public override void Brewing( ) { }
public override void XxInCup( ) { }
}