Décorateur (patron de conception)
Un article de Wikipédia, l'encyclopédie libre.
En génie logiciel, un décorateur est le nom d'une des structures de patron de conception.
Un décorateur permet d'attacher dynamiquement de nouvelles responsabilités à un objet. Les décorateurs offrent une alternative assez souple à l'héritage pour composer de nouvelles fonctionnalités.
Sommaire |
Exemple en C# [modifier]
Ici l'héritage est utilisé.
//______________________________________________________________________ // Déclarations abstract class Voiture { public abstract double Prix { get; } } class AstonMartin : Voiture { public override double Prix { get { return 999.99; } } } //______________________________________________________________________ // Décorateurs class Option : Voiture { protected Voiture _originale; protected double _tarifOption; public Option(Voiture originale, double tarif) { _originale = originale; _tarifOption = tarif; } public override double Prix { get { return _originale.Prix + _tarifOption; } } } class VoitureAvecClimatisation : Option { public VoitureAvecClimatisation (Voiture originale) : base(originale, 1.0) { } } class VoitureAvecParachute : Option { public VoitureAvecParachute (Voiture originale) : base(originale, 10.0) { } } class VoitureAmphibie : Option { public VoitureAmphibie (Voiture originale) : base(originale, 100.0) { } } //______________________________________________________________________ // Implémentation class Program { static void Main() { Voiture astonMartin= new AstonMartin(); astonMartin = new VoitureAvecClimatisation(astonMartin); astonMartin = new VoitureAvecParachute(astonMartin); astonMartin = new VoitureAvecAmphibie(astonMartin); Console.WriteLine(astonMartin.Prix); // affiche 1110.99 } }
Exemple en PHP [modifier]
<?php // Interface pour rendre un objet affichable interface Affichable { public function affiche(); } // Classe contenant un message affichable class Message implements Affichable { protected $message = ''; public function __construct($message) { $this->message = $message; } public function affiche() { echo $this->message; } } // Une classe abstraite de décoration de message affichable abstract class DecorateurDeMessage implements Affichable { protected $messageDecore = null; public function __construct(Affichable $messageDecore) { $this->messageDecore = $messageDecore; } } // Une classe pour "décorer" un message en gras class MessageEnGras extends DecorateurDeMessage { public function affiche() { echo '<strong>'; $this->messageDecore->affiche(); echo '</strong>'; } } // Une classe pour "décorer" un message en italique class MessageEnItalique extends DecorateurDeMessage { public function affiche() { echo '<em>'; $this->messageDecore->affiche(); echo '</em>'; } } // Création du message $message = new Message('le message'); // On met le message en gras et en italique $messageDecore = new MessageEnItalique( new MessageEnGras( $message ) ); // On affiche le message décoré $messageDecore->affiche(); ?>
Exemple en Java [modifier]
// ______________________________________________________________________ // Déclarations interface Voiture { public double getPrix(); } class AstonMartin implements Voiture { @Override public double getPrix() { return 999.99; } } // ______________________________________________________________________ // Décorateurs abstract class Option implements Voiture { protected Voiture _originale; protected double _tarifOption; public Option(Voiture originale, double tarif) { _originale = originale; _tarifOption = tarif; } @Override public double getPrix() { return _originale.getPrix() + _tarifOption; } } class VoitureAvecClimatisation extends Option { public VoitureAvecClimatisation(Voiture originale) { super(originale, 1.0); } } class VoitureAvecParachute extends Option { public VoitureAvecParachute(Voiture originale) { super(originale, 10.0); } } class VoitureAmphibie extends Option { public VoitureAmphibie(Voiture originale) { super(originale, 100.0); } } public class Usine { // ______________________________________________________________________ // Implémentation public static void main(String[] args) { Voiture astonMartin = new VoitureAvecClimatisation(new AstonMartin()); // Climatisation de série astonMartin = new VoitureAvecParachute(astonMartin); // Ajout d'une option (décorateur) astonMartin = new VoitureAmphibie(astonMartin); System.out.println(String.format("Prix = %.2f€", astonMartin.getPrix())); // affiche "Prix = 1110,99€" } }
Exemple en Delphi [modifier]
source : Delphi GOF DesignPatterns (CodePlex)
Exemple en Delphi
unit decorator; interface type IComponent = interface ['{8021ECE2-0D60-4C96-99AA-C5A6C515DF52}'] function Operation(): String; End; TComponent = class (TInterfacedObject, IComponent) public function Operation(): String; end; TDecoratorA = class (TInterfacedObject, IComponent) private FComponent: IComponent; public function Operation(): String; constructor Create(c: IComponent); end; TDecoratorB = class (TInterfacedObject, IComponent) private FComponent: IComponent; public addedState: String; function Operation(): String; function AddedBehaviour(): String; constructor Create(c: IComponent); end; TClient = class class procedure Display(s: String; c: IComponent); end; implementation { TComponent } function TComponent.Operation: String; begin Result := 'I am walking '; end; { TDecoratorA } constructor TDecoratorA.Create(c: IComponent); begin inherited Create; Self.FComponent := c; end; function TDecoratorA.Operation: String; var s: String; begin s := Self.FComponent.Operation; s := s + 'and listening to Classic FM '; Result := s; end; { TDecoratorB } function TDecoratorB.AddedBehaviour: String; begin Result := 'and I bouth a capuccino '; end; constructor TDecoratorB.Create(c: IComponent); begin inherited Create; Self.FComponent := c; Self.addedState := 'past the coffe shop '; end; function TDecoratorB.Operation: String; var s: String; begin s := Self.FComponent.Operation; s := s + 'to school '; Result := s; end; { TClient } class procedure TClient.Display(s: String; c: IComponent); begin WriteLn(s + c.Operation); end; end. { projet } program Structural.Decorator.Pattern; {$APPTYPE CONSOLE} uses SysUtils, decorator in 'decorator.pas'; var component, decoratorA, decoratorB: IComponent; decB: TDecoratorB; begin try WriteLn('Decorator Pattern' + #10); component := TComponent.Create; try decoratorA := TDecoratorA.Create(component); decoratorB := TDecoratorB.Create(component); TClient.Display('1. Basic component : ', component); TClient.Display('2. A-Decorated : ', decoratorA); TClient.Display('3. B-Decorated : ', decoratorB); decoratorB := TDecoratorB.Create(decoratorA); TClient.Display('4. B-A-Decorated : ', decoratorB); decB := TDecoratorB.Create(component); decoratorA := TDecoratorA.Create(decB); TClient.Display('5. A-B-Decorated : ', decoratorA); WriteLn(decB.addedState + decB.AddedBehaviour); finally component.Free; end; ReadLn; except on E:Exception do Writeln(E.Classname, ': ', E.Message); end; end.
Notes et références [modifier]
- Le patron "décorateur" sur le site developpez.com
- (en) Description par Vince Huston
- (en) Decorator Pattern
- (en) C# Conception par James W. Cooper
- (en) Approche PHP et redecorée
- (en) Approche Delphi
- (en) Article Trois approches java pour "décorer" votre code" par Michael Feldman
- (en) Article "Utiliser le patron "décorateur"" par Budi Kurniawan