2018-02-09 00:22:00 UTC
Template Pattern (Template class and Template method)
The Template Method pattern is simply a fancy way of saying that if you want to vary an algorithm, one way to do so is to code the invariant part in a base class and to encapsulate the variable parts in methods that are defined by a number of subclasses.
The base class can simply leave the methods completely undefined—in that case, the subclasses must supply the methods.
Alternatively, the base class can provide a default implementation for the methods that the subclasses can override if they want.
The general idea of the Template Method pattern is to build an abstract base class(Template Class) with a skeletal method. This skeletal method (also called a template method) drives the bit of the processing that needs to vary, but it does so by making calls to abstract methods, which are then supplied by the concrete subclasses. We pick the variation that we want by selecting one of those concrete subclasses.
Non-abstract methods that can be overridden in the concrete classes of the Template Method pattern are called hook methods.
1. You can find a classic example of the Template Method pattern in WEBrick, the lightweight, all-Ruby library for building TCP/IP servers. A key part of WEBrick is the GenericServer class, which implements all of the details of being a network server. Of course, GenericServer has no idea what you want to actually accomplish in your server. Thus, to use GenericServer, you simply extend it and override the run method:
require 'webrick' class HelloServer < WEBrick::GenericServer def run(socket) socket.print('Hello TCP/IP world') end end
The template method buried inside GenericServer contains all the code for listening on a TCP/IP port, accepting new connections, and cleaning up when a connection is a connection, it calls your run method.
2. There is another very common example of the Template Method pattern that is perhaps so pervasive that it is hard to see. Think about the initialize method that we use to set up our objects. All we know about initialize is that it is called sometime
toward the end of the process of creating a new object instance and that it is a method that we can override in our class to do any specific initialization. In other words, It's a hook method.
Imagine that your first real Ruby project is to write a report generator—that is, a program that will spew out monthly status
reports. Your reports need to be formatted in reasonably attractive HTML, so you come up with something like this:
Now suppose,your formatting object needs to produce plain text reports along with the current HTML. We will probably need PostScript and maybe RTF output before the year is out.
Sometimes the simplest solutions are the best, so you just code your way around the problem in the dumbest possible way as shown:
This second version may work, but it is a mess.The code to handle the plain text formatting is tangled up with the HTML code. Worse, as you add more formats (remember that looming requirement for PostScript!), you will have to go back and
rework the Report class to accommodate each new format. The way the code stands right now, each time you add a new format you risk breaking the code for the other formats
The way out of this quandary is to refactor this mess into a design that separates the code for the various formats. The key in doing so is to realize that no matter which format is involved—whether plain text or HTML or the future PostScript—the basic
flow of Report remains the same:
1. Output any header information required by the specific format.
2. Output the title.
3. Output each line of the actual report.
4. Output any trailing stuff required by the format
With this approach, we have one subclass for each output format. Here is our new, abstract Report class
Note: Of course, this new Report class is not really an abstract class. While we might talk in theory about abstract methods and classes, the fact is that Ruby supports neither. The ideas of abstract methods and classes do not really fit with Ruby’s easygoing, dynamic view of life. The closest we can come is to raise exceptions should anyone try to call one of our “abstract” methods
With our new Report implementation in hand, we can now define a Report subclass for each of our two formats. Here is the HTML class:
Sometimes we want default actions for some methods in the abstract base class. It reduces the clutter in the subclasses.
In that case, we can provide default non-abstract methods which can be extended if needed in the subclasses but provides a default action if not overridden. In the above example, we can change few abstract methods into hooks, which provide default implementations.
This is pretty much the summation of a widely used constructor pattern called Template design pattern
Owned & Maintained by Saurav Prakash
If you like what you see, you can help me cover server costs or buy me a cup of coffee though donation :)