我比较喜欢吃,但是自己不会做,每次想吃什么了就买了原料,然后很不熟练的收拾,然后:媳妇,做饭了,我给你准备好了;妈,做饭了,我给你切好菜了。哎,一种寄人篱下的感觉。但是我还是比较喜欢我老妈做的菜,因为我媳妇做的饭菜一般都很清淡。
我们来模拟一下我媳妇做菜的类,做菜的步骤有:准备原料、烹饪、开吃、刷盘子。看看我媳妇怎么做:
public class wife_cook {
public void Prepare() {
System.out.print("放开那棵菜,我来洗!\n");
}
public void Cook() {
System.out.print("放油,放盐,不放鸡精,不放辣椒!\n");
}
public void ClearAway() {
System.out.print("别动,我来刷盘子!\n");
}
}
应用场景场景很简单:
public class Client {
public static void main(String[] args) {
// TODO Auto-generated method stub
wife_cook cooker = new wife_cook();
cooker.Prepare();
cooker.Cook();
cooker.ClearAway();
}
}
偶尔老妈来我们家,给我做饭,这时候如果实现老妈做菜的类,要考虑到都是我洗菜和刷盘子,只不过做菜的方式有变化,考虑后面可能还有人给我做饭,出于开放-封闭原则,将做菜类抽象出来,实现如下方案:
厨师基类:
public abstract class Cooker {
public void Prepare() {
System.out.print("放开那棵菜,我来洗!\n");
}
public abstract void Cook();
public void ClearAway() {
System.out.print("别动,我来刷盘子!\n");
}
}
具体厨师:
public class Mother extends Cooker{
@Override
public void Cook() {
System.out.print("放油,放盐,放鸡精,多放辣椒!\n");
}
}
public class Wife extends Cooker{
@Override
public void Cook() {
System.out.print("放油,放盐,不放鸡精,不放辣椒!\n");
}
}
应用场景:
public class Client {
public static void main(String[] args) {
// TODO Auto-generated method stub
Cooker cooker = new Mother();//new Wife();
cooker.Prepare();
cooker.Cook();
cooker.ClearAway();
}
}
这样很大程度上已经对做菜进行了封装,但是大家会发现,两个人都会放油,放盐。那么,如果我后宫佳丽三千,你每实现一个具体的厨师,都要重复的实现放油,放盐。如果哪次你实现的过程中忘记放油了,那么这个厨师做出来的菜肯定就没法吃了,估计吃完了你也不想刷盘子。也就是说,放油、放盐这些操作是相同的甚至是不可或缺的。这个时候我们可以使用模板模式。
模板模式:定义一个算法的骨架,将一些步骤延迟到子类中去实现,使得子类在不改变算法结构的前提下即可重定义该算法的某些特定步骤。
一、特征
1、骨架:在基类中实现算法的结构流程以及相同的步骤,这样充分的对该算法进行抽象,达到复用的目的。
2、延迟:骨架类创建一些虚函数,用于子类派生并实现重定义的步骤。骨架类在算法中以一定的逻辑结构调用这些虚函数并实现那些相同的步骤,从而达到实现该算法的目的;派生类重新实现骨架类的虚函数来重定义这些步骤即可。这样在应用场景中使用基类引用即可实现多态效果。
二、实现
抽象父类(AbstractClass):实现了模板方法,定义了算法的骨架。
具体类(ConcreteClass):实现抽象类中的抽象方法,即不同的对象的具体实现细节。
我们来看看如何使用模板模式重新实现做菜这件事儿:
创建算法骨架:
public abstract class TemplateCooker {
public void Prepare() {
System.out.print("放开那棵菜,我来洗!\n");
}
public void Cook()
{
System.out.print("放油,放盐,");
AddSeasoning();
}
public void ClearAway() {
System.out.print("别动,我来刷盘子!\n");
}
protected abstract void AddSeasoning();
}
具体厨师:
public class TemplateMother extends TemplateCooker{
@Override
protected void AddSeasoning() {
System.out.print("放鸡精,多放辣椒!\n");
}
}
public class TemplateWife extends TemplateCooker{
@Override
protected void AddSeasoning() {
System.out.print("不放鸡精,不放辣椒!\n");
}
}
应用场景:
public class Client {
public static void main(String[] args) {
// TODO Auto-generated method stub
TemplateCooker cooker = new TemplateWife();//new TemplateMother();
cooker.Prepare();
cooker.Cook();
cooker.ClearAway();
}
}
这样可以最大限度地进行代码复用,同时使得代码易维护,易扩展;