Java/Design Pattern/Template Pattern
Template Method Pattern
<source lang="java">
//[C] 2002 Sun Microsystems, Inc.--- import java.io.Serializable; import java.util.ArrayList; import java.util.Iterator; public class RunTemplateMethodPattern {
public static void main(String [] arguments){ System.out.println("Example for the Template Method pattern"); System.out.println("This code demonstrates how the template method can"); System.out.println(" be used to define a variable implementation for a"); System.out.println(" common operation. In this case, the ProjectItem"); System.out.println(" abstract class defines the method getCostEstimate,"); System.out.println(" which is a combination of the cost for time and"); System.out.println(" materials. The two concrete subclasses used here,"); System.out.println(" Task and Deliverable, have different methods of"); System.out.println(" providing a cost estimate."); System.out.println(); System.out.println("Creating a demo Task and Deliverable"); System.out.println(); Task primaryTask = new Task("Put a JVM on the moon", "Lunar mission as part of the JavaSpace program ;)", 240.0, 100.0); primaryTask.addProjectItem(new Task("Establish ground control", "", 1000.0, 10.0)); primaryTask.addProjectItem(new Task("Train the Javanaughts", "", 80.0, 30.0)); Deliverable deliverableOne = new Deliverable("Lunar landing module", "Ask the local garage if they can make a few minor modifications to one of their cars", 2800, 40.0, 35.0); System.out.println("Calculating the cost estimates using the Template Method, getCostEstimate."); System.out.println(); System.out.println("Total cost estimate for: " + primaryTask); System.out.println("\t" + primaryTask.getCostEstimate()); System.out.println(); System.out.println("Total cost estimate for: " + deliverableOne); System.out.println("\t" + deliverableOne.getCostEstimate()); }
} abstract class ProjectItem implements Serializable{
private String name; private String description; private double rate; public ProjectItem(){} public ProjectItem(String newName, String newDescription, double newRate){ name = newName; description = newDescription; rate = newRate; } public void setName(String newName){ name = newName; } public void setDescription(String newDescription){ description = newDescription; } public void setRate(double newRate){ rate = newRate; } public String getName(){ return name; } public String getDescription(){ return description; } public final double getCostEstimate(){ return getTimeRequired() * getRate() + getMaterialsCost(); } public double getRate(){ return rate; } public String toString(){ return getName(); } public abstract double getTimeRequired(); public abstract double getMaterialsCost();
} class Task extends ProjectItem{
private ArrayList projectItems = new ArrayList(); private double taskTimeRequired; public Task(){ } public Task(String newName, String newDescription, double newTaskTimeRequired, double newRate){ super(newName, newDescription, newRate); taskTimeRequired = newTaskTimeRequired; } public void setTaskTimeRequired(double newTaskTimeRequired){ taskTimeRequired = newTaskTimeRequired; } public void addProjectItem(ProjectItem element){ if (!projectItems.contains(element)){ projectItems.add(element); } } public void removeProjectItem(ProjectItem element){ projectItems.remove(element); } public double getTaskTimeRequired(){ return taskTimeRequired; } public Iterator getProjectItemIterator(){ return projectItems.iterator(); } public double getMaterialsCost(){ double totalCost = 0; Iterator items = getProjectItemIterator(); while (items.hasNext()){ totalCost += ((ProjectItem)items.next()).getMaterialsCost(); } return totalCost; } public double getTimeRequired(){ double totalTime = taskTimeRequired; Iterator items = getProjectItemIterator(); while (items.hasNext()){ totalTime += ((ProjectItem)items.next()).getTimeRequired(); } return totalTime; }
} class Deliverable extends ProjectItem{
private double materialsCost; private double productionTime; public Deliverable(){ } public Deliverable(String newName, String newDescription, double newMaterialsCost, double newProductionTime, double newRate){ super(newName, newDescription, newRate); materialsCost = newMaterialsCost; productionTime = newProductionTime; } public void setMaterialsCost(double newCost){ materialsCost = newCost; } public void setProductionTime(double newTime){ productionTime = newTime; } public double getMaterialsCost(){ return materialsCost; } public double getTimeRequired(){ return productionTime; }
}
</source>
Template pattern in Java
<source lang="java">
/* The Design Patterns Java Companion Copyright (C) 1998, by James W. Cooper IBM Thomas J. Watson Research Center
- /
import java.awt.Color; import java.awt.Graphics; import java.awt.Point; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.Vector; import javax.swing.JFrame; import javax.swing.JPanel; public class TriangleDrawing extends JFrame {
stdTriangle t, t1; IsocelesTriangle it; public TriangleDrawing() { super("Draw triangles"); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); TPanel tp = new TPanel(); t = new stdTriangle(new Point(10, 10), new Point(150, 50), new Point( 100, 75)); it = new IsocelesTriangle(new Point(150, 100), new Point(240, 40), new Point(175, 150)); t1 = new stdTriangle(new Point(150, 100), new Point(240, 40), new Point(175, 150)); tp.addTriangle(t); tp.addTriangle(it); // tp.addTriangle(t1); getContentPane().add(tp); setSize(300, 200); setBackground(Color.white); setVisible(true); } public static void main(String[] arg) { new TriangleDrawing(); }
} class TPanel extends JPanel {
Vector triangles; public TPanel() { triangles = new Vector(); } public void addTriangle(Triangle t) { triangles.addElement(t); } public void paint(Graphics g) { for (int i = 0; i < triangles.size(); i++) { Triangle tngl = (Triangle) triangles.elementAt(i); tngl.draw(g); } }
} abstract class Triangle {
Point p1, p2, p3; public Triangle(Point a, Point b, Point c) { //save p1 = a; p2 = b; p3 = c; } public void draw(Graphics g) { //This routine draws a general triangle drawLine(g, p1, p2); Point current = draw2ndLine(g, p2, p3); closeTriangle(g, current); } public void drawLine(Graphics g, Point a, Point b) { g.drawLine(a.x, a.y, b.x, b.y); } //this routine is the "Hook" that has to be implemented //for each triangle type. abstract public Point draw2ndLine(Graphics g, Point a, Point b); public void closeTriangle(Graphics g, Point c) { //draw back to first point g.drawLine(c.x, c.y, p1.x, p1.y); }
} class stdTriangle extends Triangle {
public stdTriangle(Point a, Point b, Point c) { super(a, b, c); } public Point draw2ndLine(Graphics g, Point a, Point b) { g.drawLine(a.x, a.y, b.x, b.y); return b; }
} class IsocelesTriangle extends Triangle {
Point newc; int newcx, newcy; int incr; public IsocelesTriangle(Point a, Point b, Point c) { super(a, b, c); double dx1 = b.x - a.x; double dy1 = b.y - a.y; double dx2 = c.x - b.x; double dy2 = c.y - b.y; double side1 = calcSide(dx1, dy1); double side2 = calcSide(dx2, dy2); if (side2 < side1) incr = -1; else incr = 1; double slope = dy2 / dx2; double intercept = c.y - slope * c.x; //move point c so that this is an isoceles triangle newcx = c.x; newcy = c.y; while (Math.abs(side1 - side2) > 1) { newcx += incr; //iterate a pixel at a time until close newcy = (int) (slope * newcx + intercept); dx2 = newcx - b.x; dy2 = newcy - b.y; side2 = calcSide(dx2, dy2); } newc = new Point(newcx, newcy); } //calculate length of side private double calcSide(double dx, double dy) { return Math.sqrt(dx * dx + dy * dy); } //draws 2nd line using saved new point public Point draw2ndLine(Graphics g, Point b, Point c) { g.drawLine(b.x, b.y, newc.x, newc.y); return newc; }
}
</source>