Dekoratør (designmønster)
Den aktuelle version af siden er endnu ikke blevet gennemgået af erfarne bidragydere og kan afvige væsentligt fra den
version , der blev gennemgået den 19. september 2018; checks kræver
19 redigeringer .
Dekoratør |
---|
dekoratør |
|
Type |
strukturel |
Formål |
for dynamisk forbindelse til objektet for yderligere forpligtelser |
fordele |
- der er ikke behov for at oprette underklasser for at udvide objektets funktionalitet;
- evnen til dynamisk at inkludere ny funktionalitet før eller efter objektets hovedfunktionalitet ConcreteComponent.
|
Relaterede skabeloner |
Facade , Adapter |
Beskrevet i Design Patterns |
Ja |
En dekoratør er et strukturelt designmønster designet til dynamisk at forbinde yderligere adfærd til et objekt . Decorator-mønsteret giver et fleksibelt alternativ til praksis med underklassificering for at udvide funktionaliteten.
Nøglefunktioner
Udfordring
Objektet, der formodes at blive brugt, udfører hovedfunktionerne. Det kan dog være nødvendigt at tilføje noget ekstra funktionalitet til det, der kører før, efter eller endda i stedet for objektets hovedfunktionalitet.
Løsning
Dekoratøren sørger for at udvide funktionaliteten af et objekt uden at definere underklasser.
Medlemmer
En klasse ConcreteComponent er en klasse, hvortil der tilføjes ny funktionalitet ved hjælp af Decorator-mønsteret. I nogle tilfælde leveres den underliggende funktionalitet af klasser, der stammer fra ConcreteComponent. I sådanne tilfælde er klassen ConcreteComponentikke længere konkret, men abstrakt . En abstrakt klasse Componentdefinerer en grænseflade til brug af alle disse klasser.
Konsekvenser
- Den ekstra funktionalitet er implementeret i små objekter. Fordelen er muligheden for dynamisk at tilføje denne funktionalitet før eller efter hovedfunktionaliteten i ConcreteComponent.
- Giver dig mulighed for at undgå overbelastning med funktionelle klasser på de øverste niveauer af hierarkiet
- Dekorator og dens komponenter er ikke identiske
Implementering
Der oprettes en abstrakt klasse, der repræsenterer både den oprindelige klasse og de nye funktioner, der er tilføjet klassen. I dekoratørklasser kaldes nye funktioner i den ønskede rækkefølge, enten før eller efter det næste objekt kaldes.
Hvis det ønskes, er det fortsat muligt at bruge den oprindelige klasse (uden at udvide funktionaliteten), hvis en reference til dens objekt er bevaret.
Noter og kommentarer
- Selvom et dekorationsobjekt kan tilføje sin funktionalitet før eller efter funktionaliteten af hovedobjektet, skal kæden af oprettede objekter altid ende med et objekt af klasse ConcreteComponent.
- Basisklasserne i Java-sproget gør udstrakt brug af Decorator-mønsteret til at håndtere I/O-operationer.
- Både dekoratøren og adapteren er omslag omkring en genstand - de gemmer en reference til den indpakkede genstand og sender ofte metodekald til den. Forskellen mellem en dekoratør og en adapter er, at adapteren har en ekstern grænseflade, der er forskellig fra grænsefladen på den indpakkede genstand, og den bruges netop til at forbinde forskellige grænseflader. Dekoratøren derimod har nøjagtig samme interface, og bruges til at tilføje funktionalitet.
- Det er muligt at bruge både dekoratører og strategier til at udvide funktionaliteten af en klasse . Dekoratører pakker objektet udefra, mens strategier indsættes i det inde gennem bestemte grænseflader.
- Ulempen ved strategi er, at klassen skal være designet til at tillade indsættelse af strategier, men dekoratøren kræver ikke en sådan støtte.
- Ulempen ved dekoratøren er, at den omslutter præcis den samme grænseflade, som er beregnet til omverdenen, hvilket forårsager forvirring mellem den offentlige grænseflade og tilpasningsgrænsefladen, hvilket ikke altid er ønskeligt.
Anvendelse af en skabelon
Filterdrivere i Windows -kernen ( WDM (Windows Driver Model) -arkitektur ) er dekoratorer. På trods af det faktum, at WDM er implementeret i et ikke-objekt C -sprog , viser det tydeligt designmønstre - en dekoratør, en kæde af ansvarsområder og en kommando ( irp- objekt ).
COM (Component Object Model) -arkitekturen understøtter ikke implementeringsarv, i stedet foreslås det at bruge dekoratorer (i denne arkitektur kaldes dette "aggregation"). Samtidig løser arkitekturen (ved hjælp af pUnkOuter-mekanismen) det objektidentitetsproblem, der opstår ved brug af dekoratører - identiteten af et aggregat er identiteten af dets yderste dekoratør.
Eksempler
Kotlin
Et eksempel i Kotlin
fun main () {
LoggingNotifier (
FancyNotifier (
ConsoleNotifier ()
) )
). underrette ( "Hej, verden!" )
}
interface Notifier {
sjov notify ( message : String )
}
class ConsoleNotifier : Notifier {
override fun notify ( message : String ) {
println ( message )
}
}
class LoggingNotifier ( privat val notifier : Notifier ) : Notifier {
override fun notify ( meddelelse : String ) {
notifier . underrette ( besked )
println ( " LOG - $ besked " ) // Som en logger
}
}
klasse FancyNotifier ( privat val notifier : Notifier ) : Notifier {
override fun notify ( meddelelse : String ) {
val border = "-" . gentag ( meddelelseslængde ) underretning . _ _ underrette ( """ $ kant
$ besked
$ grænse
""" . trimIndent ())
}
}
Ruby
Eksempel i
Ruby
modul DecoratorPattern
# Udvider grundlæggende funktionalitet ved at kombinere flere Decoratorer
klasse Source
def initialize ( line )
@line = line
end
def write_line
@line
end
end
# Abstrakt Decorator
modul Decorator
def initialize ( source )
@source = source
end
def write_line
raise NotImplementedError
end
end
# Betondekorator
klasse Upcaser
inkluderer Decorator
def write_line
@kilde . skrive_linje . upcase
ende
ende
# Betondekoratørklasse Tidsstempel inkluderer
dekoratør
def write_line
" #{ Time . now . strftime ( '%H:%m' ) } #{ @source . write_line } " end end
#
Betondekoratør klasse Datostempler inkluderer dekoratør
def write_line
" #{ Time . now . strftime ( '%d.%m.%y' ) } #{ @source . write_line } " end end
def selv . køre
sætter '=> Dekoratør'
kilde = kilde . ny ( 'Lorem ipsum dolor sit amet' )
sætter "Kilde: \n => #{ source . write_line } "
upcased = Upcaser . new ( source )
sætter "Upcased: \n => #{ upcased . write_line } "
tidsstemplet = tidsstempel . new ( source )
sætter "Timesamped: \n => #{ timestamped . write_line } "
datestamped = datostempel . new ( source )
sætter "Datestamped: \n => #{ datestamped . write_line } "
upcased_timestamped = Tidsstempel . new ( Upcaser . new ( source ))
sætter "Upcased and timestamped: \n => #{ upcased_timestamped . write_line } "
upcased_datestamped_timestamped = Datostemplet . new ( Tidsstempler . ny ( Upcaser . ny ( kilde )))
sætter "Upcased, datestamped and timestamped: \n => #{ upcased_datestamped_timestamped . write_line } "
datestamped_timestamped = Datestamped . new ( Timesamped . new ( source ))
sætter "Datestamped and timestamped: \n => #{ datestamped_timestamped . write_line } "
sætter ' '
ende
Dekoratørmønster . løb
# => Dekoratør
# Kilde:
# => Lorem ipsum dolor sit amet
# Upcased:
# => LOREM IPSUM DOLOR SIT AMET
# Tidsstemplet:
# => 18:03 Lorem ipsum dolor sit amet
# Datostemplet:
# => 03/29/ 19 Lorem ipsum dolor sit amet
# Upcased og tidsstemplet:
# => 18:03 LOREM IPSUM DOLOR SIT AMET
# Upcased, datostemplet og tidsstemplet:
# => 03/29/19 18:03 LOREM IPSUM DOLOR SIT AMET
# Datestamped:
# => 03/29 .19 18:03 Lorem ipsum dolor sit amet
Java
Java eksempel
offentlig grænseflade InterfaceComponent {
void doOperation ();
}
klasse MainComponent implementerer InterfaceComponent {
@Override
public void doOperation () {
System . ud . print ( "Verden!" );
}
}
abstrakt klasse Decorator implementerer InterfaceComponent {
beskyttet InterfaceComponent- komponent ;
public Decorator ( InterfaceComponent c ) {
component = c ;
}
@Override
public void doOperation () {
component . doOperation ();
}
public void newOperation () {
System . ud . println ( "Gør ingenting" );
}
}
klasse DecoratorSpace udvider Decorator {
public DecoratorSpace ( InterfaceComponent c ) {
super ( c );
}
@Override
public void doOperation () {
System . ud . print ( "" );
super . doOperation ();
}
@Override
public void newOperation () {
System . ud . println ( "Ny rumoperation" );
}
}
klasse DecoratorComma udvider Decorator {
public DecoratorComma ( InterfaceComponent c ) {
super ( c );
}
@Override
public void doOperation () {
System . ud . print ( "," );
super . doOperation ();
}
@Override
public void newOperation () {
System . ud . println ( "Ny kommaoperation" );
}
}
klasse DecoratorHello udvider Decorator {
public DecoratorHello ( InterfaceComponent c ) {
super ( c );
}
@Override
public void doOperation () {
System . ud . print ( "Hej" );
super . doOperation ();
}
@Override
public void newOperation () {
System . ud . println ( "Ny hej operation" );
}
}
klasse Main {
public static void main ( String ... s ) {
Decorator c = new DecoratorHello ( new DecoratorComma ( new DecoratorSpace ( new MainComponent ())));
c . doOperation (); // Resultatet af programmet "Hej, verden!"
c . nyoperation (); // Ny hej operation
}
}
C#
Eksempel i C#
bruger System ;
namespace Decorator
{
class MainApp
{
static void Main ()
{
// Create ConcreteComponent and two Decorators
ConcreteComponent c = new ConcreteComponent ();
ConcreteDecoratorA dA = ny ConcreteDecoratorA ();
ConcreteDecoratorB dB = new ConcreteDecoratorB ();
// Link dekoratører
dA . SetComponent ( c );
dB . SetComponent ( dA );
d.A. _ operationer ();
Konsol . skriveLine ();
dB . operationer ();
// Vent på
brugerkonsollen . læs ();
}
}
/// <resumé>
/// Komponent - komponent
/// </summary>
/// <remarks>
/// <li>
/// <lu>definer en grænseflade for objekter, der kan være dynamisk
/// yderligere ansvar tildelt;</lu>
/// </li>
/// </remarks>
abstrakt klasse Komponent
{
public abstract void Operation ();
}
/// <resumé>
/// ConcreteComponent - konkret komponent
/// </summary>
/// <remarks>
/// <li>
/// <lu>definerer et objekt, der har yderligere ansvar</lu>
/ // </li>
/// </remarks>
class ConcreteComponent : Component
{
public override void Operation ()
{
Console . skriv ( "hej" );
}
}
/// <resumé>
/// Decorator - decorator
/// </summary>
/// <remarks>
/// <li>
/// <lu>gemmer en reference til et objekt <see cref="Component" /> og definerer en grænseflade
/// svarende til grænseflade <see cref="Component"/></lu>
/// </li>
/// </remarks>
abstract class Decorator : Component
{
protected Component component ;
public void SetComponent ( Component component )
{
this . komponent = komponent ;
}
public override void Operation ()
{
if ( component != null )
{
component . operationer ();
}
}
}
/// <resumé>
/// ConcreteDecoratorA - betondekoratør
/// </summary>
/// <remarks>
/// <li>
/// <lu>Udfører hovedopgaven</lu>
/// < / li>
/// </remarks>
class ConcreteDecoratorA : Decorator
{
public override void Operation ()
{
base . operationer ();
}
}
/// <resumé>
/// ConcreteDecorator - betondekoratør
/// </summary>
/// <remarks>
/// <li>
/// <lu>Udfører hovedopgaven + yderligere</lu>
// / </li>
/// </remarks>
class ConcreteDecoratorB : Decorator
{
public override void Operation ()
{
base . operationer ();
Konsol . Skriv ( "Fred!" );
}
}
}
C++
Eksempel i C++
#include <iostream>
#inkluder <hukommelse>
klasse IComponent {
offentligt :
virtuel void operation () = 0 ;
virtuel ~ IComponent (){}
};
klasse Komponent : offentlig IComponent {
offentligt :
virtuel void operation () {
std :: cout << "Verden!" << std :: endl ;
}
};
klasse DecoratorOne : offentlig IComponent {
std :: shared_ptr < IComponent > m_component ;
offentligt :
DecoratorOne ( std :: shared_ptr < IComponent > komponent ) : m_component ( komponent ) {}
virtuel void operation () {
std :: cout << ", " ;
m_component -> operation ();
}
};
klasse DecoratorTwo : offentlig IComponent {
std :: shared_ptr < IComponent > m_component ;
offentligt :
DecoratorTwo ( std :: shared_ptr < IComponent > komponent ) : m_komponent ( komponent ) {}
virtuel void operation () {
std :: cout << "Hej" ;
m_component -> operation ();
}
};
int main () {
DecoratorTwo obj ( std :: make_shared < DecoratorOne > ( std :: make_shared < Komponent > ()));
obj . operation (); // udskriver "Hej, verden!\n" return 0 ;
}
D
Eksempel på D-sprog
import std . stdio ;
abstrakt klasse Figur
{
beskyttet strengnavn ; _
streng getInfo ();
}
klasse Tom : Figur
{
overskriv streng getInfo ()
{
return null ;
}
}
klasse Cirkel : Figur
{
beskyttet Figur figur ;
this ( figur f )
{
figur = f ;
navn = "cirkel" ;
}
tilsidesæt streng getInfo ()
{
returner navn ~ figur . getInfo ();
}
}
klasse Bar : Figur
{
beskyttet Figur figur ;
this ( figur f )
{
figur = f ;
navn = "bar" ;
}
tilsidesætte streng getInfo ()
{
return figure . getInfo () ~ navn ;
}
}
void main ()
{
Figurfigurer = new Bar ( new Circle ( new Circle ( new Circle ( new Empty ( )))));
writeln ( figurer.getInfo ( ) ); }
Python
Nedenfor er et eksempel på implementering af designmønsteret. Der er funktions- og klassedekoratører i Python , som har et andet koncept end designmønsteret.
Python eksempel
[1]
"""
Demonstrerede dekoratører i en verden med et 10x10 gitter af værdier 0-255.
"""
import tilfældig
def s32_to_u16 ( x ):
hvis x < 0 :
tegn = 0xf000
ellers :
tegn = 0
bund = x & 0x00007fff
retur bund | skilt
def seed_from_xy ( x , y ): returner s32_to_u16 ( x ) | ( s32_to_u16 ( y ) << 16 )
klasse RandomSquare :
def __init__ ( s , seed_modifier ):
s . seed_modifier = frø_modifier
def get ( s , x , y ):
frø = frø_fra_xy ( x , y ) ^ s . seed_modifier
tilfældig . frø ( frø )
returnerer tilfældigt . randint ( 0 , 255 )
klasse DataSquare :
def __init__ ( s , initial_value = Ingen ):
s . data = [ initial_value ] * 10 * 10
def get ( s , x , y ):
returner s . data [ ( y * 10 ) + x ] # ja: disse er alle 10x10
def set ( s , x , y , u ):
s . data [ ( y * 10 ) + x ] = u
klasse CacheDecorator :
def __init__ ( s , dekoreret ):
s . dekoreret = dekoreret
s . cache = DataSquare ()
def get ( s , x , y ):
hvis s . cache . få ( x , y ) == Ingen :
s . cache . sæt ( x , y , s . dekoreret . få ( x , y ) )
retur s . cache . få ( x , y )
klasse MaxDecorator :
def __init__ ( s , dekoreret , max ):
s . dekoreret = dekoreret
s . max = max
def get ( s , x , y ):
hvis s . dekoreret . få ( x , y ) > s . max :
afkast s . max
afkast s . dekoreret . få ( x , y )
klasse MinDecorator :
def __init__ ( s , dekoreret , min ):
s . dekoreret = dekoreret
s . min = min
def get ( s , x , y ):
hvis s . dekoreret . få ( x , y ) < s . min :
retur s . min
retur s . dekoreret . få ( x , y )
klasse VisibilityDecorator :
def __init__ ( s , dekoreret ):
s . dekoreret = dekoreret
def få ( s , x , y ):
returnere s . dekoreret . få ( x , y )
def draw ( s ):
for y i området ( 10 ):
for x i området ( 10 ):
udskriv " %3d " % s . få ( x , y ),
print
# Opbyg nu en pipeline af dekoratører:
random_square = RandomSquare ( 635 )
random_cache = CacheDecorator ( random_square )
max_filtered = MaxDecorator ( random_cache , 200 )
min_filtered = MinDecorator ( max_filtred , 100 )
final = VisibilityDecorator ( min_filtered )
endelig . tegne ()
Output (bemærk brugen af en pseudo-tilfældig talgenerator):
100 100 100 100 181 161 125 100 200 200 100
100 200 200 200 200 200 200 184 162 100 155 200 200 200 200 200 143 100 200 144 2001 143 114 200 166 136 100 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 144 161 100 200 200 200 190 125 100 177 150 200 100 175 111 195 195 128 100 100 100 200 200 200 200 129 105 112 100 101 200 200 100 100 100 101 120 180 200 100 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001
PHP
PHP eksempel
abstrakt klasse AbstractComponent
{
abstrakt offentlig funktion operation ();
}
klasse ConcreteComponent udvider AbstractComponent
{
public function operation ()
{
// ...
}
}
abstrakt klasse AbstractDecorator udvider AbstractComponent
{
protected $component ;
offentlig funktion __construct ( AbstractComponent $component )
{
$this -> component = $component ;
}
}
class ConcreteDecorator udvider AbstractDecorator
{
public function operation ()
{
// ... udvidet funktionalitet ...
$this -> component -> operation ();
// ... udvidet funktionalitet ...
}
}
$decoratedComponent = new ConcreteDecorator (
ny ConcreteComponent ()
);
$decoratedComponent -> operation ();
PHP 5
PHP5 eksempel mest almindeligt brugt
<?php
interface IText
{
public function show ();
}
klasse TextHello implementerer IText
{
protected $object ;
offentlig funktion __construct ( IText $tekst ) {
$this -> objekt = $tekst ;
}
public function show () {
echo 'Hej' ;
$dette -> objekt -> vis ();
}
}
class TextWorld implementerer IText
{
protected $object ;
offentlig funktion __construct ( IText $tekst ) {
$this -> objekt = $tekst ;
}
public function show () {
echo 'verden' ;
$dette -> objekt -> vis ();
}
}
class TextSpace implementerer IText
{
protected $object ;
offentlig funktion __construct ( IText $tekst ) {
$this -> objekt = $tekst ;
}
public function show () {
echo ' ' ;
$dette -> objekt -> vis ();
}
}
klasse TextEmpty implementerer IText
{
public function show () {
}
}
$decorator = new TextHello ( ny TextSpace ( ny TextWorld ( ny TextEmpty ())));
$decorator -> vis (); // Hello world
echo '<br />' . PHP_EOL ;
$decorator = new TextWorld ( ny TextSpace ( ny TextHello ( ny TextEmpty ())));
$decorator -> vis (); // Hej Verden
CoffeeScript
Eksempel i CoffeeScript
# Komponentklasse
Notebook # Markedsføringspris :
500 # $
# Specifikationer
hdd : 320 # GB
ram : 4 # GB
kerne : 'i5 2.3' # GHz
# Dekoratørklasse
NovaNotebook - konstruktør: (produkt) -> @pris
= produkt . pris * 1,3
# Dekoratørklasse
ImportNotebook - konstruktør: (produkt) -> @pris
= produkt . pris * 1,5
# Dekoratørklasse
AppleNotebook - konstruktør: (produkt) -> @pris
= produkt . pris * 2,1
macBookInRussia = ny ImportNotebook ny NovaNotebook ny AppleNotebook ny Notebook
-konsol . log ( macBookInRussia .price ) _
JavaScript
JavaScript eksempel
Dekoratørmønsteret i dynamisk indtastede sprog kan bruges uden grænseflader og traditionel OOP-arv.
Dette eksempel er kopieret fra den engelske version af artiklen. Beregning af prisen på kaffe:
// ConcreteComponent (klasse til at dekorere senere)
funktion Kaffe () {
this . pris = funktion () {
return 1 ;
};
}
// Dekorator A
funktion Mælk ( kaffe ) {
dette . pris = funktion () {
returnere kaffe . pris () + 0,5 ;
};
}
// Dekorator B
funktion Pisk ( kaffe ) {
dette . pris = funktion () {
returnere kaffe . pris () + 0,7 ;
};
}
// Dekorator C
funktion Drys ( kaffe ) {
dette . pris = funktion () {
returnere kaffe . pris () + 0,2 ;
};
}
// Kan bruges sådan her:
var coffee = new Milk ( new Whip ( new Sprinkles ( new Coffee ())));
advarsel ( kaffe.pris ( ) ) ;
// Eller mere visuelt:
var kaffe = ny kaffe ();
kaffe = nyt Drys ( kaffe );
kaffe = ny Pisk ( kaffe );
kaffe = ny Mælk ( kaffe );
advarsel ( kaffe.pris ( ) );
Implementering af ovenstående C# eksempel. Der er tilføjet en lokal variabel pris til ConcreteComponent , som vil ændre sig både i sig selv og hos dekoratører. Klassenavnene (bortset fra postfixerne "A" og "B") er de samme som navnene på skabelonmedlemmerne.
function Component () {
this . operation = funktion () { };
dette . getPrice = funktion () { };
dette . setPrice = funktion () { };
}
function ConcreteComponent () {
var price = 10 ;
dette . operation = funktion () {
pris += 4 ;
alert ( "Betonkomponent. operation, pris: " + pris );
};
dette . getPrice = function () {
return price ;
};
dette . sætPris = funktion ( værdi ) {
pris = værdi ;
};
}
ConcreteComponent . prototype = ny komponent ();
Betonkomponent . prototype . constructor = ConcreteComponent ;
function Decorator () {
var komponent ;
dette . sætKomponent = funktion ( val ) {
komponent = val ;
};
dette . getComponent = function () {
return komponent ;
};
dette . operation = funktion () {
komponent . operation ();
};
dette . getPrice = funktion () {
return komponent . getpris ();
};
dette . sætPris = funktion ( værdi ) {
komponent . sætpris ( val );
};
}
Dekoratør . prototype = ny komponent ();
Dekoratør . prototype . konstruktør = Dekoratør ;
function ConcreteDecoratorA () {
Decorator . ring ( dette );
var operation = dette . drift ; // reference til metoden defineret i Decorator
dette . operation = funktion () {
dette . setPrice ( denne . getPrice () + 3 );
advarsel ( "ConcreteDecoratorA. operation, pris: " + denne . getPrice ());
operation ();
};
}
function ConcreteDecoratorB () {
var duplicate = this ; // reference til det instansierede objekt (fordi dette kan ændre sig)
Decorator . ring ( dette );
var operation = dette . drift ; // reference til metoden defineret i Decorator
dette . operation = funktion () {
dette . setPrice ( this.getPrice ( ) + 1 ) ; advarsel ( "ConcreteDecoratorB. operation, pris: " + denne . getPrice ()); tilføjet adfærd (); operation (); };
function addedBehavior () {
duplicate . setPrice ( duplicate . getPrice () + 2 );
advarsel ( "addedBehavior, price: " + duplicate . getPrice ());
}
}
// brug
c = ny ConcreteComponent ();
d1 = new ConcreteDecoratorA ();
d2 = new ConcreteDecoratorB ();
advarsel ( "original pris: " + c . getPrice ()); // ti
d1 . sætKomponent ( c );
d2 . sætKomponent ( d1 );
d2 . operation ();
advarsel ( "pris efter konvertering: " + c . getPrice ()); // tyve
VB.NET
Eksempel i VB.NET
Navnerumsdekoratør _
klasse program
Shared Sub Main ()
' Opret ConcreteComponent og to dekoratører
Dim C As New ConcreteComponent ()
Dim D1 As New ConcreteDecoratorA ()
Dim D2 As New ConcreteDecoratorB ()
' Dekoratørreferencer
D1 . SetComponent ( C )
D2 . SetComponent ( D1 )
D2 . operation ()
'Venter på handling fra
brugerkonsollen . Læs ()
End Sub
slutklasse _
''' <summary>
''' Komponent - komponent
''' </summary>
''' <remarks>
''' <li>
''' <lu>definer en grænseflade for objekter, der dynamisk kan tildeles
''' yderligere ansvar;</lu>
''' </li>
''' </remarks>
MustInherit Class Component
Public MustOverride Sub Operation ()
End Class
''' <summary>
''' ConcreteComponent - konkret komponent
''' </summary>
''' <remarks>
''' <li>
''' <lu>definerer et objekt, der har yderligere ansvar</lu>
' '' </li>
''' </remarks>
Klasse ConcreteComponent
arver komponent
Offentlige tilsidesættelser Sub Operation ()
Konsol . WriteLine ( "ConcreteComponent.Operation()" )
End Sub
End Class
''' <summary>
''' Dekoratør - dekoratør
''' </summary>
''' <remarks>
''' <li>
''' <lu> gemmer en reference til et objekt <see cref="Component" /> og definerer en grænseflade
''' svarende til grænseflade <see cref="Component"/></lu>
''' </li>
''' </remarks>
MustInherit Class Decorator
arver komponent
Beskyttet komponent som komponent
Public Sub SetComponent ( ByVal component As Component )
Me . komponent = komponent
End Sub
Offentlige tilsidesættelser Underoperation ( )
Hvis komponent ikke er noget , så
komponent . Operation ()
End If
End Sub
End Class
''' <summary>
''' ConcreteDecorator - betondekoratøren
''' </summary>
''' <remarks>
''' <li>
''' <lu>lægger yderligere ansvar på komponenten.</lu>
'' ' </li>
''' </remarks>
Klasse ConcreteDecoratorA
arver Decorator
Private addedState As String
Offentlige tilsidesættelser Sub Operation ()
MyBase . Operation ()
addedState = "Ny tilstand"
-konsol . WriteLine ( "ConcreteDecoratorA.Operation()" )
End Sub
End Class
' "BetonDecoratorB"
Klasse BetonDecoratorB
arver Decorator
Offentlige tilsidesættelser Sub Operation ()
MyBase . Operation ()
AddedBehavior ()
Konsol . WriteLine ( "ConcreteDecoratorB.Operation()" )
End Sub
Private Sub AddedBehavior ()
End Sub
End Class
End Namespace
Delphi
Delphi og Free Pascal støtter klassehjælpere, som gør brugen af dekorationsmønstret unødvendig .
Delphi eksempel
program NoMoreDecorators ;
type
TMyObject = klasse
procedure WriteHello ;
ende ;
TMyObjectHelper = klassehjælper for TMyObject - proceduren WriteHello ( const Navn : string ) ; overbelastning ; ende ;
procedure TMyObject . Skriv Hej ;
start
writeln ( 'Hej' ) ;
ende ;
procedure TMyObjectHelper . WriteHello ( const Navn : streng ) ;
start
writeln ( 'Hej, ' , Navn , '!' ) ;
ende ;
var
o : TMyObject ;
start
o := TMyObject . skabe ;
o . Skriv Hej ;
o . WriteHello ( 'Jean' ) ;
o . Gratis ;
ende .
Delphi eksempel
program DecoratorPattern ;
{$APPTYPE KONSOL}
bruger
SysUtils ;
type
TInterfaceComponent = klasse
offentlig
procedure Operation ; virtuel ; abstrakt ;
ende ;
type
TConcreteComponent = klasse ( TInterfaceComponent )
offentlig
procedure Operation ; tilsidesætte ;
ende ;
procedure TConcreteComponent . drift ;
begynde
Skriv ( 'kan ikke' ) ;
ende ;
type
TDecorator = klasse ( TInterfaceComponent )
privat
FComponent : TInterfaceComponent ;
offentlig
konstruktør Opret ( aComponent : TInterfaceComponent ) ;
ende ;
konstruktør TDecorator . Opret ( aComponent : TInterfaceComponent ) ;
start
FComponent := aComponent ;
ende ;
type
TBeforeDecorator = klasse ( TDecorator )
offentlig
procedure Drift ; tilsidesætte ;
ende ;
procedure TBeforeDecorator . drift ;
begynde
Skriv ( 'Udfør,' ) ;
FComponent . drift ;
ende ;
type
TAfterDecorator = klasse ( TDecorator )
offentlig
procedure Drift ; tilsidesætte ;
ende ;
procedure TAefterDecorator . drift ;
start
FComponent . drift ;
Skriv ( 'undskyld' ) ;
ende ;
type
TOverrideDecorator = klasse ( TDecorator )
offentlig
procedure Drift ; tilsidesætte ;
ende ;
procedure TOverrideDecorator . drift ;
begynde
Skriv ( 'Elsk hinanden!' ) ;
ende ;
var
vSameComponent : TInterfaceComponent ;
start
vSameComponent := TAfterDecorator . Opret ( TConcreteComponent . Opret ) ;
vSameComponent . drift ; // Vil udskrive "kan ikke benåde"
Writeln ;
vSameComponent := TBeforeDecorator . Opret ( vSameComponent ) ;
vSameComponent . drift ; // Vil udskrive "Execute, can't pardon"
Writeln ;
vSameComponent := TOverrideDecorator . Opret ( vSameComponent ) ;
vSameComponent . drift ; // Vil udskrive "Elsk hinanden!"
// For nemheds skyld er ødelæggelsen af objekter ikke vist
Læsln ;
ende .
Swift
Hurtigt eksempel
protokol Bog {
var title : String { get set }
var price : Int { get set }
func getPrice () -> Int
}
klasse BookImpl : Bog {
var title : String = ""
var pris : Int = 1000
func getPrice () - > Int {
returpris }
}
klasse Rabatbog : Bog {
let element : BookImpl
var title : String = "Groaming Algorithms"
var pris : Int = 0
init ( element : BookImpl ) {
self . element = element
selv . titel = element . titel
selv . pris = element . pris
}
// 30 % udsalg
func getPrice () - > Int {
returpris - ( pris * 30 ) / 100 }
}
// Brug Decorator
lad bog = BookImpl ()
lad rabatBook = Rabatbog ( element : bog )
print ( rabatBook . getPrice ())
Litteratur
- Alan Shalloway, James R. Trott. Design mønstre. En ny tilgang til objektorienteret design = Designmønstre forklaret: Et nyt perspektiv på objektorienteret design. - M . : "Williams" , 2002. - S. 288. - ISBN 0-201-71594-5 .
- Eric Freeman, Elizabeth Freeman. Designmønstre = Head First Design Patterns. - Sankt Petersborg. : Peter. — 656 s. - ISBN 978-5-459-00435-9 .
Noter
- ↑ Dekoratørmønster . wiki.python.org . Hentet 24. oktober 2021. Arkiveret fra originalen 24. oktober 2021. (ubestemt)
Links