设计模式之模板方法模式
模板方法模式定义了一套算法调用步骤的模板,通过继承,子类可以对一个或多个步骤提供实现。当需要扩展时,只需要添加子类即可,而且子类可以复用父类的代码。
模板方法模式的类图如下:
下面以泡茶和冲咖啡为例
抽象出泡茶和冲咖啡的咖啡因饮料类
/**
定义了模板方法的类,抽象出咖啡和茶的咖啡因饮料类
**/
public abstract class CaffeineBeverage
{
/**
模板方法,调用一系列的步骤,实现制作饮料的步骤
**/
public final void prepareRecipe()
{
boilWater();
brew();
pourInCup();
if(custormerWantCondiments())
addCondiments();
}
/**
由于把水煮沸的步骤对于任何饮料都是一样的,则父类直接实现该方法
**/
public void boilWater()
{
System.out.println("boil water");
}
public abstract void brew();
public abstract void addCondiments();
public void pourInCup()
{
System.out.println("pour In cup");
}
/**
子类可以选择实现的“钩子”方法
**/
public boolean custormerWantCondiments()
{
return true;
}
}
Tea类
/**
继承了模板方法的类Tea,没有实现钩子方法
**/
public class Tea extends CaffeineBeverage
{
public void brew()
{
System.out.println("Steeping the tea");
}
public void addCondiments()
{
System.out.println("adding lemon");
}
}
Coffee类
import java.io.*;
/**
继承了模板方法的类Coffee类
**/
public class Coffee extends CaffeineBeverage
{
public void brew()
{
System.out.println("Dripping Coffee through filter");
}
public void addCondiments()
{
System.out.println("adding sugar");
}
/**
子类可以选择实现的“钩子”方法
**/
public boolean custormerWantCondiments()
{
String answer=getUserInput();
if(answer.equals("y"))
{
return true;
}
return false;
}
private String getUserInput()
{
String answer=null;
System.out.println("would you like milk and sugar in your coffee?");
BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
try
{
answer=in.readLine();
}
catch (IOException e)
{
e.printStackTrace();
}
if(answer==null)
{
return "n";
}
return answer;
}
}
测试类
public class Test
{
public static void main(String[] args)
{
Coffee coffee=new Coffee();
System.out.println("Making coffee....");
coffee.prepareRecipe();
Tea tea=new Tea();
System.out.println("Making tea....");
tea.prepareRecipe();
}
}
运行结果
可以看出模板方法定义的步骤里面有三种不同类型的方法:
1.由父类直接实现的方法:比如上例中的boilWater和pourInCup方法,对于Coffee和Tea来说,都是一样的,所以可以复用,可以定义为final
2.由子类实现的方法:比如上例中的brew方法
3.子类可选择实现的方法,比如上例中的customerWantCondiments()方法。
由模板方法模式中的“钩子”,可以引申出一个设计原则——“好莱坞原则”,“别电话给我,我会打电话给你”,就是说,低层组件可以将自己挂钩到系统上,但是由高层组件决定什么时候和怎样使用这些底层组件,所以对于高层组件来说,其对待低层组件的方式是“别调用我,我会调用你们”。像上例中的customerWantCondiments()方法,就是由子类实现,父类调用。
模板方法的应用之一是用模板方法排序。
Arrays类中提供了一个sort方法,sort方法实际上调用了一个私有的mergeSort()方法
mergeSort方法是一个模板方法,我们可以通过改变比较的条件实现自己的排序,我们需要实现的是Comparable接口中的compareTo()方法。
比如说我们要将学生按成绩排序。
写一个Student类,实现Comparable接口
public class Student implements Comparable
{
public int score;
public String name;
public Student(String name,int score)
{
this.name=name;
this.score=score;
}
public int compareTo(Object object)
{
Student otherStudent=(Student)object;
if(this.score>otherStudent.score)
{
return 1;
}
else if(this.score==otherStudent.score)
{
return 0;
}
else
{
return -1;
}
}
}
测试类
import java.util.*;
public class TestSort
{
public static void main(String[] args)
{
Student[] stu={
new Student("qing",100),
new Student("chen",90),
new Student("zhou",80),
new Student("ddd",50)
};
System.out.println("before sorting....");
display(stu);
System.out.println("after sorting....");
Arrays.sort(stu);
display(stu);
}
public static void display(Student[] stu)
{
for(Student s:stu)
{
System.out.println(s.name+"\t"+s.score);
}
}
}
运行结果是
模板方法模式,策略模式,工厂方法模式的比较
浙公网安备 33010602011771号