一:定义:
Template Method :Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure.
二:引入
一个咖啡店,卖咖啡和茶。
制作咖啡的步骤是:
把水煮开。 放入咖啡。 把煮好的咖啡倒进杯子。 加糖或奶。
制作茶的步骤是:
把水煮开。 放入茶叶。 把茶倒进茶杯。 加柠檬或其他调料。
public
class
Coffee
...
{ public void prepareRecipe() ... { boilWater(); brew(); pourInCup(); addCondiments(); } void boilWater() ... { System.out.println( " boil water " ); } public void brew() ... { System.out.println( " brew coffee " ); } void pourInCup() ... { System.out.println( " pour in cup " ); } public void addCondiments() ... { System.out.println( " add sugar " ); } }
public
class
Tea
...
{ public void prepareRecipe() ... { boilWater(); brew(); pourInCup(); addCondiments(); } void boilWater() ... { System.out.println( " boil water " ); } public void brew() ... { System.out.println( " brew tea " ); } void pourInCup() ... { System.out.println( " pour in cup " ); } public void addCondiments() ... { System.out.println( " add lemon " ); } }
我们发现,制作两种饮料的方法有些地方是类似的,我们可以对这两个类进行抽象。
public
abstract
class
CaffeineBeverage
...
{ public final void prepareRecipe() ... { boilWater(); brew(); pourInCup(); addCondiments(); } void boilWater() ... { System.out.println( " boil water " ); } void pourInCup() ... { System.out.println( " pour in cup " ); } abstract void brew(); abstract void addCondiments(); }
public
class
Coffee
extends
CaffeineBeverage
...
{ public void brew() ... { System.out.println( " brew coffee " ); } public void addCondiments() ... { System.out.println( " add sugar " ); } }
public
class
Client
...
{ public static void main(String[] args) ... { CaffeineBeverage beverage = new Coffee(); beverage.prepareRecipe(); } }
父类提供了一个按步骤执行方法的模板,公共部分已经在父类实现,其它由具体子类自己实现。
三:结构
四:实际应用
javx.servlet.http.HttpServlet
HttpServlet代码,doGet等方法由子类实现。
public
abstract
class
HttpServlet
extends
GenericServlet
implements
Serializable
...
{ protected void service(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException ... { if (request.getMethod().equals( " GET " ) ) ... { if (testConditional(request,response)) doGet(request,response); } else if (request.getMethod().equals( " HEAD " ) ) ... { if (testConditional(request,response)) doHead(request,response); } else if (request.getMethod().equals( " POST " ) ) ... { doPost(request,response); } else if (request.getMethod().equals( " DELETE " ) ) ... { doDelete(request,response); } else if (request.getMethod().equals( " OPTIONS " ) ) ... { doOptions(request,response); } else if (request.getMethod().equals( " PUT " ) ) ... { doPut(request,response); } else if (request.getMethod().equals( " TRACE " ) ) ... { doTrace(request,response); } else ... { response.sendError(HttpServletResponse.SC_BAD_REQUEST, " Method " " + request.getMethod() + " " is not supported by this servlet " ); } } protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException