Dekoratér (šéf designu)

Tento článek může obsahovat nepublikovanou práci nebo neověřená prohlášení (října 2014).

Můžete pomoci přidáním odkazů nebo odebráním nepublikovaného obsahu. Další podrobnosti najdete na diskusní stránce .

V softwarovém inženýrství je dekorátor název jedné ze struktur návrhových vzorů .

Dekorátor umožňuje dynamicky přiřadit nové odpovědnosti k objektu . Dekoratéři nabízejí dostatečně flexibilní alternativu k dědičnosti, aby mohli vytvářet nové funkce.

Přehled

Vzor dekorátoru je jedním z dvaceti tří vzorů GOF . Řeší následující problémy:

Při použití dědičnosti rozšiřují různé podtřídy nadřazenou třídu různými způsoby. Ale rozšíření je připojeno ke třídě v době kompilace a nemůže se změnit za běhu.

Příklad Java

// ______________________________________________________________________ // Déclarations public interface IVehicule { public String getNom(); public String getMarque(); public int getPrix(); public int getPoids(); } public abstract class Voiture implements IVehicule { private String aNom; private String aMarque; protected void setNom(String pNom) { this.aNom = pNom; } public String getNom() { return this.aNom; } protected void setMarque(String pMarque) { this.aMarque = pMarque; } public String getMarque() { return this.aMarque; } } public class DS extends Voiture { public DS() { this.setNom("DS"); this.setMarque("Citroën"); } public int getPrix() { return 30000; } public int getPoids() { return 1500; } } // ______________________________________________________________________ // Décorateurs public abstract class VoitureAvecOption extends Voiture { private IVehicule aVehicule; protected void setVehicule(IVehicule pVehicule) { this.aVehicule = pVehicule; } public IVehicule getVehicule() { return this.aVehicule; } } class VoitureAvecToitOuvrant extends VoitureAvecOption { public int getPrix() { return this.getVehicule().getPrix() + 10000; } public int getPoids() { return this.getVehicule().getPoids() + 15; } } //On garde le nom du pattern Decorator pour savoir qu'on wrap un objet class DSAvecToitOuvrantDecorator extends VoitureAvecToitOuvrant { public DSAvecToitOuvrantDecorator(DS pDS) { this.setVehicule(pDS); } } public class Main { // ______________________________________________________________________ // Implémentation public static void main(String[] args) { DS vDS = new DS(); IVehicule vDSOption = new DSAvecToitOuvrantDecorator(vDS); System.out.println(vDSOption.getPoids() + " - " + vDSOption.getPrix()); } }


Příklad v C #

Zde se používá dědictví.

//______________________________________________________________________ // 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 VoitureAmphibie(astonMartin); Console.WriteLine(astonMartin.Prix); // affiche 1110.99 } }

Příklad v C ++

# include <iostream> # include <memory> class IVoiture { public: virtual double prix() = 0; }; class Aston_martin : public IVoiture { public: double prix() override { return 999.99l; } }; class Option_voiture : public IVoiture { public: Option_voiture(std::unique_ptr<IVoiture> voiture, double prix_option) : voiture_(std::move(voiture)) , prix_option_(prix_option) {} double prix() override { return voiture_->prix() + prix_option_; } protected: std::unique_ptr<IVoiture> voiture_; double prix_option_; }; class Option_clim : public Option_voiture { public: Option_clim(std::unique_ptr<IVoiture> voiture) : Option_voiture(std::move(voiture), 1.0) {} }; class Option_parachute : public Option_voiture { public: Option_parachute(std::unique_ptr<IVoiture> voiture) : Option_voiture(std::move(voiture), 10.0) {} }; class Option_amphibie : public Option_voiture { public: Option_amphibie(std::unique_ptr<IVoiture> voiture) : Option_voiture(std::move(voiture), 100.0) {} }; int main() { auto voiture = std::unique_ptr<IVoiture>(std::make_unique<Aston_martin>()); voiture = std::make_unique<Option_clim>(std::move(voiture)); voiture = std::make_unique<Option_parachute>(std::move(voiture)); voiture = std::make_unique<Option_amphibie>(std::move(voiture)); std::cout << voiture->prix() << "\n"; // affiche 1110.99 return 0; }

Příklad v PHP

<?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(); ?>

Příklad v Delphi

Jazyky Delphi a Free Pascal skutečně podporují pomocníky tříd, díky nimž je návrhový vzor dekorátoru zbytečný .

program NoMoreDecorators; type TMyObject = class procedure WriteHello; end; TMyObjectHelper = class helper for TMyObject procedure WriteHello(const Name: string); overload; end; procedure TMyObject.WriteHello; begin writeln('Hello'); end; procedure TMyObjectHelper.WriteHello(const Name: string); begin writeln('Hello, ', Name, '!'); end; var o: TMyObject; begin o := TMyObject.Create; o.WriteHello; o.WriteHello('Jean'); o.Free; end.

zdroj: Delphi GOF DesignPatterns (CodePlex)

Příklad v 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.  

Poznámky a odkazy

Dodatky

Související články