8a__IFT232_DesignPatterns_TemplateMethod

publicité
Template Method
Design Pattern
But
Définir le squelette d’un algorithme
tout en déléguant certaines étapes
aux sous-classes.
Les sous-classes peuvent redéfinir
certaines étapes de l’algorithme sans
en changer la structure.
Exemple
public class Application
{… public OpenDocument (String name)
{ if (!CanOpenDocument(name))
{ // cannot handle this document
return; }
Document doc =DoCreateDocument();
if (doc != null)
{ _docs.AddDocument(doc);
AboutToOpenDocument(doc);
doc.Open();
doc.DoRead();
} } }
Exemple
La méthode template définit l’algorithme en termes
d’opérations abstraites.
Les sous-classes les redéfinissent pour spécifier le
comportement concret de différentes étapes de l’algorithme
Est-ce que le document peut être ouvert? (CanOpenDocument)
Création du document (DoCreateDocument)
Lecture du document (DoRead).
Informer les sous-classes que le document va être ouvert au
cas où elles s’en préoccuperaient (AboutToOpenDocument).
La méthode “template” fixe l’ordre des opérations,
mais laisse la possibilité aux sous-classes de définir les
détails de ces opérations.
Quand appliquer
le patron Template Method?
Pour implémenter les parties invariantes d’un algorithme une
seule fois
et laisser aux sous-classes le soin d’implémenter les parties
qui varient.
Lorsqu’un comportement commun entre des sous-classes
devrait être factorisé et placé dans une classe commune afin
d’éviter la duplication de code
"refactoring to generalize"
Identifer les différences dans le code existant
Extraire ces différences dans de nouvelles méthodes
Utiliser le template method pour appeler ces méthodes
Pour contrôler les extensions des sous-classes
Définir une méthode template
qui appelle des méthodes "hook" en des points spécifiques
de manière à ne permettre les extensions seulement qu’en ces
points
Structure
Participants
AbstractClass (Application)
Définit les méthodes abstraites de base
que les sous-classes doivent implémenter
pour les diverses étapes de l’algorithme.
Implémente la méthode “template” qui définit le squelette
de l’algorithme.
Cette méthode invoque aussi bien les méthodes abstraites
que les méthodes définies dans AbstractClass ou celles
de d’autres objets.
ConcreteClass (MyApplication)
Implémente les opérations abstraites pour réaliser les
étapes spécifiques aux sous-classes
Collaborations entre les classes
ConcreteClass repose sur AbstractClass
pour l’implémentation des étapes invariantes de
l’algorithme
Exemple
Exemple : refactorisation
Classe abstraite
public abstract class TextDocument {
…
public final void printPage(Page page) {
printTextHeader();
printTextBody(page);
printTextFooter();
}
protected abstract void printTextHeader();
protected abstract void printTextBody(Page page);
protected abstract void printTextFooter();
…
}
Exemple : Refactorisation
Sous-classes
Conséquences I
Une technique fondamentale pour la réutilisation du code
Particulièrement importante dans les librairies de classes
Le moyen pour factoriser les comportements communs
Une structure de contrôle inversée
"the Hollywood principle," that is, "Don't call us, we'll call you"
La classe parent appelle les méthodes des sous-classes et non
l’inverse.
Un template method invoque en général les types de méthodes
suivants:
Méthodes concrètes de ConcreteClass ou de classes clients;
Méthodes concrètes de AbstractClass
Méthodes abstraites
factory methods
Méthodes “hook”,
Comportement par défaut que les sous-classes peuvent redéfinir
Souvent ces méthodes sont vides.
Afin de bien réutiliser une classe abstraite, il faut bien identifier
Les méthodes “hook” qui peuvent être redéfinies
Les méthodes abstraites qui doivent être redéfinies.
Conséquences II
Une sous-classe peut spécialiser une méthode d’une classe parent
en redéfinissant cette méthode
et en invoquant la méthode de la superclasse explicitement
Public class DerivedClass extends ParentClass
{ public void operation () {super.operation(); } }
Cependant, il facile d’oublier l’invocation de la méthode de la superclasse
Transformation en méthode “template” pour donner le contrôle à la
classe parent
La classe parent définit une méthode hook
que les sous-classe peuvent redéfinir
Public class ParentClass
{ “final” public void operation () {HookOperation(); }
pubic void hookOperation () { } }}
Les sous-classes redéfinissent HookOperation :
Public class DerivedClass extends ParentClass
{ public void hookOperation ()
{ // DerivedClass extended behavior
} }
Implémentation
Méthodes abstract, protected, final
Minimiser les méthodes abstraites.
Plus il y aura de méthodes à définir,
plus ce sera fastidieux
Définir des conventions au niveau des noms.
Par exemple, pour définir les méthodes qui devraient être
redéfinies, utiliser un préfixe.
Dans le MacApp framework pour les applications Macintosh
Le nom des méthodes relatives à un template method
commencent avec "Do-“
"DoCreateDocument", "DoRead", etc.
Design Patterns reliés
Factory Methods
souvent appelés par les template methods
la méthode DoCreateDocument de la méthode
OpenDocument de l’exemple.
Strategy
Les méthodes Template utilisent l’héritage pour
faire varier des parties d’un algorithme
Les stratégies utilisent la délégation pour faire
varier tout l’algorithme.
Références
William F. Opdyke and Ralph E. Johnson.
Creating abstract superclasses by
refactoring. In Proceedings of the 21st
Annual Computer Science Conference
(ACM CSC '93), pages 66–73,
Indianapolis, IN, February 1993
Rebecca Wirfs-Brock and Ralph E.
Johnson. A survey of current research in
object-oriented design. Communications of
the ACM, 33(9):104–124, 1990
Strategy DP
Define a family of algorithms, encapsulate each
one, and make them interchangeable. Strategy
lets the algorithm vary independently from
clients that use it.
Strategy - exemple
Composition class
responsible for maintaining and updating the linebreaks of text
displayed in a text viewer.
Compositor subclasses implement different strategies:
SimpleCompositor implements a simple strategy that determines
linebreaks one at a time.
TeXCompositor implements the TeX algorithm for finding linebreaks.
This strategy tries to optimize linebreaks globally, that is, one paragraph
at a time.
ArrayCompositor implements a strategy that selects breaks so that
each row has a fixed number of items. It's useful for breaking a
collection of icons into rows, for example.
A Composition maintains a reference to a Compositor object.
Whenever a Composition reformats its text, it forwards this
responsibility to its Compositor object.
Téléchargement