一、
1.The Template Method defines the steps of an algorithm and allows subclasses to provide the implementation for one or more steps.
2.The Template Method Pattern defi nes the skeleton of an algorithm in a method, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm’s structure.
3.With a hook, I can override the method, or not. It’s my choice.If I don’t, the abstract class provides a default implementation.
4.
二、
1.
1 package headfirst.designpatterns.templatemethod.barista; 2 3 public abstract class CaffeineBeverage { 4 5 final void prepareRecipe() { 6 boilWater(); 7 brew(); 8 pourInCup(); 9 addCondiments(); 10 } 11 12 abstract void brew(); 13 14 abstract void addCondiments(); 15 16 void boilWater() { 17 System.out.println("Boiling water"); 18 } 19 20 void pourInCup() { 21 System.out.println("Pouring into cup"); 22 } 23 }
2.
1 package headfirst.designpatterns.templatemethod.barista; 2 3 public abstract class CaffeineBeverageWithHook { 4 5 final void prepareRecipe() { 6 boilWater(); 7 brew(); 8 pourInCup(); 9 if (customerWantsCondiments()) { 10 addCondiments(); 11 } 12 } 13 14 abstract void brew(); 15 16 abstract void addCondiments(); 17 18 void boilWater() { 19 System.out.println("Boiling water"); 20 } 21 22 void pourInCup() { 23 System.out.println("Pouring into cup"); 24 } 25 26 boolean customerWantsCondiments() { 27 return true; 28 } 29 }
3.
1 package headfirst.designpatterns.templatemethod.barista; 2 3 public class Coffee extends CaffeineBeverage { 4 public void brew() { 5 System.out.println("Dripping Coffee through filter"); 6 } 7 public void addCondiments() { 8 System.out.println("Adding Sugar and Milk"); 9 } 10 }
4.
1 package headfirst.designpatterns.templatemethod.barista; 2 3 import java.io.*; 4 5 public class CoffeeWithHook extends CaffeineBeverageWithHook { 6 7 public void brew() { 8 System.out.println("Dripping Coffee through filter"); 9 } 10 11 public void addCondiments() { 12 System.out.println("Adding Sugar and Milk"); 13 } 14 15 public boolean customerWantsCondiments() { 16 17 String answer = getUserInput(); 18 19 if (answer.toLowerCase().startsWith("y")) { 20 return true; 21 } else { 22 return false; 23 } 24 } 25 26 private String getUserInput() { 27 String answer = null; 28 29 System.out.print("Would you like milk and sugar with your coffee (y/n)? "); 30 31 BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); 32 try { 33 answer = in.readLine(); 34 } catch (IOException ioe) { 35 System.err.println("IO error trying to read your answer"); 36 } 37 if (answer == null) { 38 return "no"; 39 } 40 return answer; 41 } 42 }
5.
1 package headfirst.designpatterns.templatemethod.barista; 2 3 public class Tea extends CaffeineBeverage { 4 public void brew() { 5 System.out.println("Steeping the tea"); 6 } 7 public void addCondiments() { 8 System.out.println("Adding Lemon"); 9 } 10 }
6.
1 package headfirst.designpatterns.templatemethod.barista; 2 3 import java.io.*; 4 5 public class TeaWithHook extends CaffeineBeverageWithHook { 6 7 public void brew() { 8 System.out.println("Steeping the tea"); 9 } 10 11 public void addCondiments() { 12 System.out.println("Adding Lemon"); 13 } 14 15 public boolean customerWantsCondiments() { 16 17 String answer = getUserInput(); 18 19 if (answer.toLowerCase().startsWith("y")) { 20 return true; 21 } else { 22 return false; 23 } 24 } 25 26 private String getUserInput() { 27 // get the user's response 28 String answer = null; 29 30 System.out.print("Would you like lemon with your tea (y/n)? "); 31 32 BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); 33 try { 34 answer = in.readLine(); 35 } catch (IOException ioe) { 36 System.err.println("IO error trying to read your answer"); 37 } 38 if (answer == null) { 39 return "no"; 40 } 41 return answer; 42 } 43 }
7.
1 package headfirst.designpatterns.templatemethod.barista; 2 3 public class BeverageTestDrive { 4 public static void main(String[] args) { 5 6 Tea tea = new Tea(); 7 Coffee coffee = new Coffee(); 8 9 System.out.println(" Making tea..."); 10 tea.prepareRecipe(); 11 12 System.out.println(" Making coffee..."); 13 coffee.prepareRecipe(); 14 15 16 TeaWithHook teaHook = new TeaWithHook(); 17 CoffeeWithHook coffeeHook = new CoffeeWithHook(); 18 19 System.out.println(" Making tea..."); 20 teaHook.prepareRecipe(); 21 22 System.out.println(" Making coffee..."); 23 coffeeHook.prepareRecipe(); 24 } 25 }
8.
三、The Hollywood Principle and Template Method
1.The Hollywood Principle Don’t call us, we’ll call you.
2.
3.
4.
5.
四、Sorting with Template Method
1.
1 package headfirst.designpatterns.templatemethod.sort; 2 3 public class Duck implements Comparable<Duck> { 4 String name; 5 int weight; 6 7 public Duck(String name, int weight) { 8 this.name = name; 9 this.weight = weight; 10 } 11 12 public String toString() { 13 return name + " weighs " + weight; 14 } 15 16 public int compareTo(Duck object) { 17 18 Duck otherDuck = object; 19 20 if (this.weight < otherDuck.weight) { 21 return -1; 22 } else if (this.weight == otherDuck.weight) { 23 return 0; 24 } else { // this.weight > otherDuck.weight 25 return 1; 26 } 27 } 28 }
五、JFrame中的templateMethod的hook方法
1.If you haven’t encountered JFrame, it’s the most basic Swing container and inherits
a paint() method. By default, paint() does nothing because it’s a hook! By overriding
paint(), you can insert yourself into JFrame’s algorithm for displaying its area of the
screen and have your own graphic output incorporated into the JFrame. Here’s
an embarrassingly simple example of using a JFrame to override the paint() hook
method:
2.
1 package headfirst.designpatterns.templatemethod.frame; 2 3 import java.awt.*; 4 import javax.swing.*; 5 6 public class MyFrame extends JFrame { 7 private static final long serialVersionUID = 2L; 8 9 public MyFrame(String title) { 10 super(title); 11 this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 12 13 this.setSize(300,300); 14 this.setVisible(true); 15 } 16 17 // JFrame’s update algorithm calls paint(). By 18 // default, paint() does nothing... it’s a hook. 19 // We’re overriding paint(), and telling the 20 // JFrame to draw a message in the window. 21 public void paint(Graphics graphics) { 22 super.paint(graphics); 23 String msg = "I rule!!"; 24 graphics.drawString(msg, 100, 100); 25 } 26 27 public static void main(String[] args) { 28 MyFrame myFrame = new MyFrame("Head First Design Patterns"); 29 } 30 }
六、Applet的hook方法
1.Concrete applets make extensive use of hooks to supply their
own behaviors. Because these methods are implemented as
hooks, the applet isn’t required to implement them.
2.
1 package headfirst.designpatterns.templatemethod.applet; 2 3 import java.applet.Applet; 4 import java.awt.Graphics; 5 6 public class MyApplet extends Applet { 7 private static final long serialVersionUID = 2L; 8 String message; 9 10 public void init() { 11 message = "Hello World, I'm alive!"; 12 repaint(); 13 } 14 15 public void start() { 16 message = "Now I'm starting up..."; 17 repaint(); 18 } 19 20 public void stop() { 21 message = "Oh, now I'm being stopped..."; 22 repaint(); 23 } 24 25 public void destroy() { 26 message = "Goodbye, cruel world"; 27 repaint(); 28 } 29 30 public void paint(Graphics g) { 31 g.drawString(message, 5, 15); 32 } 33 }
3.
七、
1.
Q: When I’m creating a template method, how do I know when to use abstract methods and when to use hooks?
A: Use abstract methods when your subclass MUST provide an implementation of the method or step in the algorithm.
Use hooks when that part of the algorithm is optional. With hooks, a subclass may choose to implement that hook, but it doesn’t have to.
2.
Q: This implementation of sorting
actually seems more like the Strategy
Pattern than the Template Method
Pattern. Why do we consider it
Template Method?
A: You’re probably thinking that
because the Strategy Pattern uses object
composition. You’re right in a way – we’re
using the Arrays object to sort our array, so
that’s similar to Strategy. But remember,
in Strategy, the class that you compose
with implements the entire algorithm. The
algorithm that Arrays implements for sort
is incomplete; it needs a class to fill in the
missing compareTo() method. So, in that
way, it’s more like Template Method.
3.
Q: Are there other examples of
template methods in the Java API?
A: Yes, you’ll find them in a few
places. For example, java.io has a read()
method in InputStream that subclasses
must implement and is used by the tempate
method read(byte b[], int off, int len).
4.
The Strategy and Template Method Patterns both encapsulate algorithms, one by inheritance and one by composition.