Article Preview
Buy Now
FEATURE
The Template-Method-Pattern
Motivation: Having some Algorithms, that differ in details, but not in Principle
Issue: 7.1 (November/December 2008)
Author: Jens Bendig
Author Bio: When he was young Jens Bendig was fascinated by three things: motorbikes, computers, and movies. Now he rides a motorbike, produces animated movies, and develops software. He seems to be a straightforward character.
Article Description: No description available.
Article Length (in bytes): 17,836
Starting Page Number: 22
Article Number: 7111
Resource File(s):
project7111.zip Updated: 2008-11-01 11:51:00
Related Link(s): None
Excerpt of article text...
I have read so many articles about haute-cuisine and molecular-cooking that today I want to write about good and honest baked potatoes. By that I mean, we often have programming problems that make our heads smoke, but sometimes those problems can be solved by an old, well-known, and simple design. Here comes such a problem and a clear, easy, and straightforward way of solving it. You'd do so in REALbasic like in any other object-oriented language. A Common Problem
Do you sometimes have a problem like this: I have 2 (or 20) Classes, they are similar in their basic algorithm (i.e., they have about the same sequence of doing things, but in detail, they are doing different things). You see that you have double code, but it's not so clear why. You'd like to get an abstraction to avoid the double code, but you are not sure about how to do so. If you derive from a Base-Class (Super-Class), doesn't that mean to carry the Algorithm to the derivatives? Or can we centralize the Algorithm in the base-class and keep the Variations for the Derivatives?
Yes, we can: with a design pattern called "Template-Method." It's helpful, if you have a fixed sequence of "something" but a lot of variations in that "something." Is it complicated to make or difficult to understand? Does it need sophisticated mechanics? No, it's just the good and straightforward use of the good old mechanism called inheritance.
...End of Excerpt. Please purchase the magazine to read the full article.
Errata (2008-11-09)
The following Code Listings were inadvertently omitted from the article.
Listing1: Code for coffeeMaker and teaMaker
// coffee-button Sub Action() dim maker as coffeeMaker maker=new coffeeMaker(output) // output is the instance-name of a listbox maker.produce() // producing means to fill the output for the user End Sub // tea-button Sub Action() dim maker as coffeeMaker maker=new coffeeMaker(output) maker.produce() End Sub //Code of the coffeeMaker-Class Sub Constructor(output as listbox) me.plog=output // keeping the output-listbox as property, my methods will log there End Sub // The algorithm of the coffee-maker: 4 Steps of production Sub produce() me.heatWater() // step1 me.filtering() // step2 me.fillCup() // step3 me.addSugarAndMilk() // step4 me.plog.AddRow("finished") me.plog.AddRow("") End Sub // Details of the algorithm, description of the 4 steps itself: Private Sub heatWater() me.plog.AddRow("Heating water...") End Sub Private Sub filtering() me.plog.AddRow("Let the Water run through a Filter with Coffee") End Sub Private Sub fillCup() me.plog.AddRow("Fill the cup with coffee") End Sub Private Sub addSugarAndMilk() me.plog.addrow "Adding sugar and milk" End Sub // Code of the teaMaker-Class Sub Constructor(output as listbox) me.plog=output // hmm. looks exactly the same as the constructor of the coffeeMaker-class End Sub Sub produce() me.heatWater() // identical to coffeeMaker step1 me.letBrew() // different to coffeeMaker step2 me.fillCup() // identical to coffeeMaker step 3 me.addCitrone() // different to coffeeMaker step 4 me.plog.AddRow("finished") me.plog.AddRow("") End Sub Private Sub heatWater() me.plog.AddRow("Heating water...") End Sub Private Sub letBrew() me.plog.AddRow("Fill the hot Water into Can with Tee-Egg") End Sub Private Sub fillCup() me.plog.AddRow("Fill the cup with Tee") End Sub Private Sub addCitrone() me.plog.addrow "Adding Citrone" End Sub
Listing 2: Abstract Base-Class hotBeverageMaker
Sub Constructor(logOutput as listbox, name as string) me.plog=logOutput me.plog.AddRow("new hot beverage: "+name) // the Parameter name will be given by the concrete hot Beverage, derived from this class End Sub // the following method is the template method: The Controller of all the derived Details Sub produce() me.heatWater() //common for all hot beverages me.pour() // depending on kind of beverage me.fillCup() // common for all hot beverages me.addIngredients() //depending on kind of beverage me.plog.AddRow("finished") // served with a smile could be put here for every Beverage! me.plog.AddRow(" ") End Sub Protected Sub heatWater() plog.AddRow("heating water") // this code will do the work for all derived classes End Sub Protected Sub pour() me.plog.AddRow("ERROR: base-class does not know how to pour") End Sub Protected Sub fillCup() me.plog.AddRow("filling the cup with"+me.pname) // this code will do the work for all derived classes End Sub Protected Sub addIngredients() me.plog.AddRow("ERROR: Don't know how to add Ingredients") End Sub
Listing3: coffeeMaker, teaMaker
// code for the coffeMaker Sub Constructor(logOuput as listbox) // Calling the overridden superclass constructor. Super.Constructor(logOuput,"Coffee") End Sub Protected Sub pour() me.plog.AddRow("putting Coffee into Filter and fill with hot Water") End Sub Protected Sub addIngredients() me.plog.AddRow("Adding some Milk and sugar for the customer") End Sub // code for the teaMaker Sub Constructor(logOuput as listbox) // Calling the overridden superclass constructor. Super.Constructor(logOuput,"Tea") End Sub Protected Sub pour() me.plog.AddRow("putting Tee into Can and fill with hot Water") End Sub Protected Sub addIngredients() me.plog.AddRow("Adding some Citrone") End Sub