Design Patterns
239 pág.

Design Patterns


DisciplinaEngenharia de Software I4.656 materiais51.838 seguidores
Pré-visualização50 páginas
is allowed. As opposed to a simple polymorphic override, where the base
method would be entirely rewritten allowing radical change to the workflow, only the specific details of the
workflow are allowed to change.
The control structure (inversion of control) that is the result of the application of a template pattern is often referred
to as the Hollywood Principle: "Don't call us, we'll call you." Using this principle, the template method in a parent
class controls the overall process by calling subclass methods as required. This is shown in the following Java
example:
Example
/**
 * An abstract class that is 
 * common to several games in
 * which players play against 
 * the others, but only one is
 * playing at a given time.
 */
abstract class Game {
 protected int playersCount;
 abstract void initializeGame();
 abstract void makePlay(int player);
 abstract boolean endOfGame();
 abstract void printWinner();
 /* A template method : */
 public final void playOneGame(int playersCount) {
 this.playersCount = playersCount;
 initializeGame();
 int j = 0;
 while (!endOfGame()) {
 makePlay(j);
 j = (j + 1) % playersCount;
 }
 printWinner();
 }
}
//Now we can extend this class in order 
//to implement actual games:
Template method pattern 182
class Monopoly extends Game {
 /* Implementation of necessary concrete methods */
 void initializeGame() {
 // Initialize players
 // Initialize money
 }
 void makePlay(int player) {
 // Process one turn of player
 }
 boolean endOfGame() {
 // Return true if game is over 
 // according to Monopoly rules
 }
 void printWinner() {
 // Display who won
 }
 /* Specific declarations for the Monopoly game. */
 // ...
}
class Chess extends Game {
 /* Implementation of necessary concrete methods */
 void initializeGame() {
 // Initialize players
 // Put the pieces on the board
 }
 void makePlay(int player) {
 // Process a turn for the player
 }
 boolean endOfGame() {
 // Return true if in Checkmate or 
 // Stalemate has been reached
 }
 void printWinner() {
 // Display the winning player
 }
 /* Specific declarations for the chess game. */
 // ...
}
Template method pattern 183
External links
\u2022 Template design pattern in C# and VB.NET [1]
\u2022 Working with Template Classes in PHP 5 [2]
\u2022 Template Method pattern in UML and in LePUS3 [3] (a formal modelling language)
\u2022 Difference between Adapter and Template Method pattern [4]
\u2022 Template Method Design Pattern [5]
References
[1] http:/ / www. dofactory. com/ Patterns/ PatternTemplate. aspx
[2] http:/ / www. devshed. com/ c/ a/ PHP/ Working-with-Template-Classes-in-PHP-5/
[3] http:/ / www. lepus. org. uk/ ref/ companion/ TemplateMethod. xml
[4] http:/ / programmersnotes. info/ 2009/ 03/ 03/ difference-between-adapter-and-template-method-pattern/
[5] http:/ / sourcemaking. com/ design_patterns/ template_method
Visitor pattern
Visitor in UML
In object-oriented programming and
software engineering, the visitor design
pattern is a way of separating an algorithm
from an object structure on which it
operates. A practical result of this separation
is the ability to add new operations to
existing object structures without modifying
those structures. It is one way to easily
follow the open/closed principle.
In essence, the visitor allows one to add new
virtual functions to a family of classes
without modifying the classes themselves;
instead, one creates a visitor class that
implements all of the appropriate
specializations of the virtual function. The
visitor takes the instance reference as input,
and implements the goal through double
dispatch.
Motivation
Consider the design of a 2D CAD system. At its core there are several types to represent basic geometric shapes like
circles, lines and arcs. The entities are ordered into layers, and at the top of the type hierarchy is the drawing, which
is simply a list of layers, plus some additional properties.
Visitor pattern 184
Visitor in LePUS3 (legend [2])
A fundamental operation on this type
hierarchy is saving the drawing to the
system's native file format. It seems
relatively fine to add local save methods to
all types in the hierarchy. But then we also
want to be able to save drawings to other
file formats, and adding more and more
methods for saving into lots of different file
formats soon clutters the relatively pure
geometric data structure we started out with.
A naive way to solve this would be to
maintain separate functions for each file
format. Such a save function would take a drawing as input, traverse it and encode into that specific file format. But
if you do this for several different formats, you soon begin to see lots of duplication between the functions, e.g. lots
of type-of if statements and traversal loops. Another problem with this approach is how easy it is to miss a certain
shape in some saver.
Instead, you could apply the Visitor pattern. The Visitor pattern encodes a logical operation on the whole hierarchy
into a single class containing one method per type. In our CAD example, each save function would be implemented
as a separate Visitor subclass. This would remove all duplication of type checks and traversal steps. It would also
make the compiler complain if you leave out a shape.
Details
The visitor pattern requires a programming language that supports single dispatch and method overloading. Under
these conditions, consider two objects, each of some class type; one is called the "element", and the other is called
the "visitor". An element has an accept() method that can take the visitor as an argument. The accept()
method calls a visit() method of the visitor; the element passes itself as an argument to the visit() method.
Thus:
\u2022 When the accept() method is called in the program, its implementation is chosen based on both:
\u2022\u2022 The dynamic type of the element.
\u2022\u2022 The static type of the visitor.
\u2022 When the associated visit() method is called, its implementation is chosen based on both:
\u2022\u2022 The dynamic type of the visitor.
\u2022 The static type of the element as known from within the implementation of the accept() method, which is
the same as the dynamic type of the element. (As a bonus, if the visitor can't handle an argument of the given
element's type, then the compiler will catch the error.)
\u2022 Consequently, the implementation of the visit() method is chosen based on both:
\u2022\u2022 The dynamic type of the element.
\u2022\u2022 The dynamic type of the visitor.
This effectively implements double dispatch; indeed, because the Lisp language's object system supports
multiple dispatch (not just single dispatch), implementing the visitor pattern in Lisp is trivial.
In this way, a single algorithm can be written for traversing a graph of elements, and many different kinds of
operations can be performed during that traversal by supplying different kinds of visitors to interact with the
elements based on the dynamic types of both the elements and the visitors.
Visitor pattern 185
Java example
The following example is in the Java programming language, and shows how the contents of a tree of nodes (in this
case describing the components of a car) can be printed. Instead of creating "print" methods for each subclass
(Wheel, Engine, Body, and Car), a single class (CarElementPrintVisitor) performs the required printing action.
Because different subclasses require slightly different actions to print properly, CarElementDoVisitor dispatches
actions based