Sometimes the general sequence of tasks a function must perform is the same across a variety of applications, suggesting that the function belongs in a common framework. However, the tasks performed by the function are application-specific, suggesting the function belongs in the various framework customizations.
The generic algorithm design pattern solves this problem. Move the function into the framework and declare the application-specific tasks to be pure virtual functions in the framework. A function like this is called a generic algorithm or a template method.[1]
Generic Algorithm [Go4], [ROG]
Other Names
Template method
Problem
Parts of an algorithm are invariant across a family of framework customizations, while other parts are not.
Solution
Move the algorithm into the framework. Replace the non-invariant parts by calls to virtual functions that can be implemented differently in different customizations.
Generic algorithms follow the inverted control structure
sometimes called the
Let's start with a trivial example to clarify the idea; more serious examples will come later. Suppose we want to add a symphony class to our music framework, MFW. Symphonies are usually divided into four movements, so playing a symphony is easy: play the first movement, then the second, then the third, finally the fourth. Of course the similarity between symphonies ends here. The particulars of each movement vary from one symphony to the next, and will have to be specified in various customizations of the framework. We can still add an abstract symphony base class to our framework, but play() will have to be a generic algorithm:
abstract class Symphony {
public void play() { // a generic
algorithm
doFirstMovement();
doSecondMovement();
doThirdMovement();
doFourthMovement();
}
protected abstract virtual void
doFirstMovement() = 0;
protected abstract virtual void
doSecondMovement() = 0;
protected abstract virtual void
doThirdMovement() = 0;
protected abstract virtual void
doFourthMovement() = 0;
}
Framework customizers will have to subclass Symphony and implement the do-functions. For example:
class TheFifth extends Symphony {
protected void doFirstMovement() {
System.out.println("dah, dah,
dah, duh ...");
}
void doSecondMovement() {
System.out.println("duh, duh,
duh, dah ...");
}
void doThirdMovement() {
System.out.println("dah, duh,
duh, dah ...");
}
void doFourthMovement() {
System.out.println("duh, dah,
dah, duh ...");
}
}