The GoF (Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides) book describes this pattern as a pattern that "Defines 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 algorithms structure."
Typically a
problem that fits the template method design pattern consist in a complex task that
can be accomplished by breaking it into several preset steps. An abstract class
contains a stub method for establishing the order of executing these steps.
Some of these steps are implemented in this abstract class (default implementation
that is common to all subclass), while the rest of steps are implemented by
subclasses (custom implementation that is specific to each subclass).
For example,
let suppose that we have a printer service. Basically, we need to set the
printer before each print, and in order to accomplish that we need to:
- check
printer ink (default implementation)
- check
cartridges (default implementation)
- feed
printer with paper (custom implementation, different paper sizes)
- align
printing margins (custom implementation, different margins depending on paper
size)
- print
style (custom implementation, color and grayscale)
The above
actions need to take place in this preset order and some of them (check print
ink and cartridges) are common actions, while others are specific actions. For
keeping this order, we need a final stub method that basically represents the
main action - printing. Since is final, subclasses cannot alter the step
order.
So, first we
need to write the abstract class that contains the stub method and the
default/custom implementations - notice that we marked the default
implementations as private because we don't want them to be callable/modifiable
from subclasses, but this is not mandatory!
public
abstract class PrinterTemplate {
//template method, final so subclasses can't
override
public final void print(){
checkInkLevel();
checkCartridges();
feedWithPaper();
alignMargins();
printStyle();
}
// default implementation
private void checkInkLevel() {
System.out.println("The printer ink
level have been check!");
}
// default implementation
private void checkCartridges() {
System.out.println("The printer
cartridges have been check!");
}
//methods to be implemented by subclasses
public abstract void feedWithPaper();
public abstract void alignMargins();
public abstract void printStyle();
}
Next, we
provide the template method concrete classes. We have A4Printing and A1Printing,
as follows:
public class
A4Printing extends PrinterTemplate {
@Override
public void feedWithPaper() {
System.out.println("Feed with paper A4
format.");
}
@Override
public void alignMargins() {
System.out.println("A4 margins:
top/1.0in, bottom/0.75in, left/0.75in, right/0.75in.");
}
@Override
public void printStyle() {
System.out.println("A4 print in
colors.");
}
}
public class
A1Printing extends PrinterTemplate {
@Override
public void feedWithPaper() {
System.out.println("Feed with paper A1
format.");
}
@Override
public void alignMargins() {
System.out.println("A1 margins
top/0.5in, bottom/0.5in, left/0.2in, right/0.2in.");
}
@Override
public void printStyle() {
System.out.println("A1 print in
grayscale.");
}
}
Finally, we
can perform a test:
PrinterTemplate
printerA1 = new A1Printing();
printerA1.print();
PrinterTemplate
printerA4 = new A4Printing();
printerA4.print();
The output
will be:
The printer
ink level have been check!
The printer
cartridges have been check!
Feed with
paper A1 format.
A1 margins
top/0.5in, bottom/0.5in, left/0.2in, right/0.2in.
A1 print in
grayscale.
The printer
ink level have been check!
The printer
cartridges have been check!
Feed with
paper A4 format.
A4 margins:
top/1.0in, bottom/0.75in, left/0.75in, right/0.75in.
A4 print in
colors.
In template
pattern, super-class template method calls methods from subclasses, this is known
as Hollywood Principle – "don’t call
us,we’ll call you".
In the next
part we will re-write this example in JSF+CDI style.
Niciun comentariu :
Trimiteți un comentariu