Sisustaja (suunnittelukuvio)
Kokeneet kirjoittajat eivät ole vielä tarkistaneet sivun nykyistä versiota, ja se voi poiketa merkittävästi 19. syyskuuta 2018 tarkistetusta
versiosta . tarkastukset vaativat
19 muokkausta .
Sisustusarkkitehti |
---|
sisustusarkkitehti |
|
Tyyppi |
rakenteellinen |
Tarkoitus |
dynaamista yhteyttä lisävelvoitteiden kohteeseen |
Plussat |
- ei tarvitse luoda alaluokkia objektin toiminnallisuuden laajentamiseksi;
- kyky sisällyttää dynaamisesti uusia toimintoja ennen kohteen päätoimintoa tai sen jälkeen ConcreteComponent.
|
Aiheeseen liittyvät mallit |
Julkisivu , sovitin |
Kuvattu suunnittelukuvioissa |
Joo |
Sisustaja on rakennesuunnittelumalli , joka on suunniteltu yhdistämään dynaamisesti lisäkäyttäytymistä esineeseen . Decorator-kuvio tarjoaa joustavan vaihtoehdon alaluokkien käytännölle toiminnallisuuden laajentamiseksi.
Tärkeimmät ominaisuudet
Haaste
Esine, jota on tarkoitus käyttää, suorittaa päätoiminnot. Siihen voi kuitenkin olla tarpeen lisätä joitain lisätoimintoja, jotka toimivat ennen, jälkeen tai jopa objektin päätoiminnon sijasta.
Ratkaisu
Sisustaja mahdollistaa kohteen toiminnallisuuden laajentamisen ilman alaluokkia.
Jäsenet
Luokka ConcreteComponent on luokka, johon lisätään uusia toimintoja Decorator-kuvion avulla. Joissakin tapauksissa taustalla olevat toiminnot tarjoavat luokat, jotka ovat peräisin ConcreteComponent. Tällaisissa tapauksissa luokka ConcreteComponentei ole enää konkreettinen, vaan abstrakti . Abstrakti luokka Componentmäärittelee käyttöliittymän kaikkien näiden luokkien käyttämiseen.
Seuraukset
- Lisätty toiminnallisuus on toteutettu pienissä objekteissa. Etuna on kyky lisätä tämä toiminto dynaamisesti ennen päätoimintoa tai sen jälkeen ConcreteComponent.
- Voit välttää ylikuormituksen toiminnallisilla luokilla hierarkian ylimmillä tasoilla
- Sisustus ja sen osat eivät ole identtisiä
Toteutus
Luodaan abstrakti luokka, joka edustaa sekä alkuperäistä luokkaa että luokkaan lisättyjä uusia funktioita. Sisustusluokissa uudet funktiot kutsutaan vaaditussa järjestyksessä joko ennen seuraavan objektin kutsumista tai sen jälkeen.
Haluttaessa on edelleen mahdollista käyttää alkuperäistä luokkaa (toiminnallisuutta laajentamatta), jos viittaus sen objektiin on säilytetty.
Huomautuksia ja kommentteja
- Vaikka sisustusobjekti voi lisätä toiminnallisuutensa ennen pääobjektin toiminnallisuutta tai sen jälkeen, luotujen objektien ketjun tulee aina päättyä luokan objektiin ConcreteComponent.
- Java-kielen perusluokat hyödyntävät laajasti Decorator-mallia I/O-toimintojen käsittelyssä.
- Sekä koristelija että sovitin käärivät kohteen ympärille - ne tallentavat viittauksen käärittyyn kohteeseen ja lähettävät sille usein menetelmäkutsuja. Erona sisustajan ja sovittimen välillä on se, että sovittimessa on ulkoinen liitäntä, joka eroaa käärityn esineen rajapinnasta ja jota käytetään nimenomaan eri liitäntöjen yhdistämiseen. Sen sijaan sisustajalla on täsmälleen sama käyttöliittymä, ja sitä käytetään lisäämään toimintoja.
- Luokan toiminnallisuuden laajentamiseen on mahdollista käyttää sekä sisustajia että strategioita . Sisustajat käärivät esineen ulkopuolelta, kun taas strategiat työnnetään siihen sisälle tiettyjen rajapintojen kautta.
- Strategian haittana on, että luokka on suunniteltava siten, että se mahdollistaa strategioiden lisäämisen, mutta sisustaja ei tarvitse tällaista tukea.
- Decoratorin haittana on, että se käärii täsmälleen saman rajapinnan, joka on tarkoitettu ulkomaailmalle, mikä aiheuttaa sekaannusta julkisen käyttöliittymän ja räätälöintirajapinnan välillä, mikä ei aina ole toivottavaa.
Mallin käyttäminen
Windows -ytimen suodatinohjaimet ( WDM (Windows Driver Model) -arkkitehtuuri ) ovat koristeita. Huolimatta siitä, että WDM on toteutettu ei-objekti C -kielellä , se näyttää selkeästi suunnittelumallit - sisustajan, vastuuketjun ja komennon ( irp- objekti ).
COM (Component Object Model) -arkkitehtuuri ei tue toteutuksen periytymistä, vaan sen sijaan ehdotetaan käytettäväksi koristeita (tässä arkkitehtuurissa tätä kutsutaan "aggregaatioksi"). Samalla arkkitehtuuri ratkaisee (pUnkOuter-mekanismin avulla) sisustajia käytettäessä esiin tulevan objektin identiteettiongelman - aggregaatin identiteetti on sen uloimman sisustajan identiteetti.
Esimerkkejä
Kotlin
Esimerkki Kotlinista
fun main () {
LoggingNotifier (
FancyNotifier (
ConsoleNotifier ()
)
). ilmoittaa ( "Hei, maailma!" )
}
käyttöliittymän ilmoittaja {
hauska ilmoitus ( viesti : merkkijono )
}
luokka ConsoleNotifier : Notifier {
ohita hauska ilmoitus ( viesti : merkkijono ) {
println ( viesti )
}
}
luokka LoggingNotifier ( yksityinen val notifier : Notifier ) : Ilmoittaja {
ohita hauska ilmoitus ( viesti : String ) {
ilmoitus . ilmoittaa ( viesti )
println ( "LOG - $ viesti " ) // Kuin logger
}
}
class FancyNotifier ( yksityinen val notifier : Notifier ) : Notifier {
ohita hauska ilmoitus ( viesti : String ) {
val border = " - " . toista ( viesti . pituus )
ilmoitus . notify ( """
$ border
$ viesti
$ raja
""" . trimIndent ())
}
}
Ruby
Esimerkki
Rubyssa
moduuli DecoratorPattern
# Laajentaa perustoimintoja yhdistämällä useita koristeita
luokka Lähde
def alustaa ( rivi )
@rivi = rivin
loppu
def write_line
@rivin
loppu
_
# Abstract Decorator
module Decorator
def alustus ( lähde )
@ lähde = lähde
loppu
def write_line
raise NotImplementedError
end
end
# Concrete Decorator
Class Upcaser
sisältää Decoratorin
def write_line
@source . kirjoitusrivi . upcase
loppu
_
# Concrete Decorator
Class Timestamper
sisältää Decoratorin
def write_line
" #{ Aika . nyt . strftime ( '%H:%m' ) } #{ @ lähde . write_line } " end end
# Concrete Decorator
Class Datestamper
sisältää Decoratorin
def write_line
" #{ Aika . nyt . strftime ( '%d.%m.%y' ) } #{ @source . write_line } " end end
itsevarmasti . _ run laittaa '=> sisustaja'
lähde = lähde . new ( 'Lorem ipsum dolor sit amet' )
laittaa "Lähde: \n => #{ source . write_line } "
ylöskirjoitettu = Upcaser . new ( lähde )
laittaa "Upcased: \n => #{ upcased . write_line } "
aikaleima = aikaleima . new ( lähde )
laittaa "Timestamped: \n => #{ timestamped . write_line } "
päivämääräleima = päivämääräleima . new ( lähde )
laittaa "Päiväleima: \n => #{ datestamped . write_line } "
upcased_timestamped = Aikaleima . new ( Upcaser . new ( lähde ))
laittaa "Upcased and timestamped: \n => #{ upcased_timestamped . write_line } "
upcased_datestamped_timestamped = Päiväysleimattu . new ( Timestamper . new ( Upcaser . new ( lähde )))
laittaa "Upcased, datestamped ja timestamped: \n => #{ upcased_datestamped_timestamped . write_line } "
datestamped_timestamped = Päivämääräleima . new ( Timestamped . new ( lähde ))
asettaa "Päiväleima ja aikaleima: \n => #{ datestamped_timestamped . write_line } "
laittaa ' '
lopun
Sisustuskuvio . juosta
# => Sisustaja
# Lähde:
# => Lorem ipsum dolor sit amet
# Upcased:
# => LOREM IPSUM DOLOR SIT AMET
# Aikaleima:
# => 18:03 Lorem ipsum dolor sit amet
# Päiväysleimaus:
# => 03/29/ 19 Lorem ipsum dolor sit amet
# Upcased ja aikaleima:
# => 18:03 LOREM IPSUM DOLOR SIT AMET
# Upcased, päivämääräleima ja aikaleima:
# => 03/29/19 18:03 LOREM IPSUM DOLOR SIT AMET
# Datestamped:
# => 03/29 .19 18:03 Lorem ipsum dolor sit amet
Java
Java esimerkki
julkinen käyttöliittymä InterfaceComponent {
void doOperation ();
}
luokka MainComponent toteuttaa InterfaceComponent {
@Override
public void doOperation () {
Järjestelmä . ulos . tulosta ( "Maailma!" );
}
}
abstrakti luokka Decorator toteuttaa InterfaceComponent {
suojattu InterfaceComponent komponentti ;
public Decorator ( InterfaceComponent c ) {
komponentti = c ;
}
@Override
public void doOperation () {
komponentti . doOperation ();
}
public void newOperation () {
Järjestelmä . ulos . println ( "Älä tee mitään" );
}
}
luokka DecoratorSpace laajentaa Decorator {
public DecoratorSpace ( InterfaceComponent c ) {
super ( c );
}
@Override
public void doOperation () {
Järjestelmä . ulos . tulostaa ( "" );
super . doOperation ();
}
@Override
public void newOperation () {
Järjestelmä . ulos . println ( "Uusi avaruusoperaatio" );
}
}
luokka DecoratorComma laajentaa sisustaja {
public DecoratorComma ( InterfaceComponent c ) {
super ( c );
}
@Override
public void doOperation () {
Järjestelmä . ulos . tulostaa ( "," );
super . doOperation ();
}
@Override
public void newOperation () {
Järjestelmä . ulos . println ( "Uusi pilkkutoiminto" );
}
}
luokka SisustajaHei laajentaa sisustaja {
public DecoratorHei ( InterfaceComponent c ) {
super ( c );
}
@Override
public void doOperation () {
Järjestelmä . ulos . tulosta ( "Hei" );
super . doOperation ();
}
@Override
public void newOperation () {
Järjestelmä . ulos . println ( "Uusi hello-operaatio" );
}
}
luokka pää {
public static void main ( Merkkijono ... s ) {
Sisustaja c = new DecoratorHei ( new DecoratorComma ( new DecoratorSpace ( new MainComponent ())));
c . doOperation (); // Ohjelman "Hei, maailma!"
c . uusiOperaatio (); // Uusi hello-operaatio
}
}
C#
Esimerkki C#:ssa
käyttäen System ;
nimitila Decorator
{
class MainApp
{
static void Main ()
{
// Luo ConcreteComponent ja kaksi koristelua
ConcreteComponent c = new ConcreteComponent ();
ConcreteDecoratorA dA = uusi ConcreteDecoratorA ();
ConcreteDecoratorB dB = uusi ConcreteDecoratorB ();
// Linkkikoristelijat
dA . SetComponent ( c );
dB . SetComponent ( dA );
d.A. _ operaatiot ();
konsoli . writeLine ();
dB . operaatiot ();
// Odota käyttäjän
konsolia . lue ();
}
}
/// <summary>
/// Komponentti - komponentti
/// </summary>
/// <remarks>
/// <li>
/// <lu>määritä käyttöliittymä objekteille, jotka voivat olla dynaamisesti
/// ylimääräisiä määrätyt vastuut;</lu>
/// </li>
/// </remarks>
abstract class Komponentti
{
public abstract void Operaatio ();
}
/// <summary>
/// ConcreteComponent - betonikomponentti
/// </summary>
/// <remarks>
/// <li>
/// <lu>määrittää objektin, jolla on lisävastuita</lu>
/ // </li>
/// </remarks>
class ConcreteComponent : Komponentti
{
public override void Operation ()
{
Konsoli . kirjoittaa ( "hei" );
}
}
/// <summary>
/// Sisustaja - sisustaja
/// </summary>
/// <huomautus>
/// <li>
/// <lu>talloittaa viittauksen objektiin <katso cref="Komponentti" /> ja määrittää rajapinnan
/// joka vastaa käyttöliittymää <katso cref="Komponentti"/></lu>
/// </li>
/// </remarks>
abstrakti luokka Decorator : Komponentti
{
suojattu Komponenttikomponentti ;
public void SetComponent ( komponenttikomponentti ) { this . _ komponentti = komponentti ; }
julkinen ohitus void Operaatio ()
{
if ( komponentti != null )
{
komponentti . operaatiot ();
}
}
}
/// <summary>
/// ConcreteDecoratorA - betonisuunnittelija
/// </summary>
/// <huomautus>
/// <li>
/// <lu>Suorittaa päätehtävän</lu>
/// < / li>
/// </remarks>
class ConcreteDecoratorA : Sisustaja
{
public override void Operation ()
{
base . operaatiot ();
}
}
/// <summary>
/// ConcreteDecorator - betonisuunnittelija
/// </summary>
/// <remarks>
/// <li>
/// <lu>Suorittaa päätehtävän + lisätyö</lu>
// / </li>
/// </remarks>
class ConcreteDecoratorB : Sisustaja
{
public override void Operation ()
{
base . operaatiot ();
konsoli . Kirjoita ( "Rauha!" );
}
}
}
C++
Esimerkki C++:ssa
#include <iostream>
#sisällytä <muisti>
class IComponent {
julkinen :
virtuaalinen tyhjiötoiminto ( ) = 0 ;
virtuaalinen ~ IComponent (){}
};
class Komponentti : public IComponent {
julkinen :
virtuaalinen tyhjä toiminta () {
std :: cout << "Maailma!" << std :: endl ;
}
};
luokka DecoratorOne : julkinen IComponent {
std :: jaettu_ptr < IComponent > m_component ;
julkinen :
DecoratorOne ( std :: jaettu_ptr < IComponent > komponentti ) : m_komponentti ( komponentti ) {}
virtuaalinen tyhjä toiminta () {
std :: cout << ", " ;
m_komponentti -> operaatio ();
}
};
luokka DecoratorTwo : julkinen IComponent {
std :: jaettu_ptr < IComponent > m_component ;
julkinen :
DecoratorTwo ( std :: jaettu_ptr < IComponent > komponentti ) : m_komponentti ( komponentti ) {}
virtuaalinen tyhjä toiminta () {
std :: cout << "Hei" ;
m_komponentti -> operaatio ();
}
};
int main () {
DecoratorTwo obj ( std :: make_shared < DecoratorOne > ( std :: make_shared < Komponentti > ()));
obj . operaatio (); // tulostaa "Hei, maailma!\n" return 0 ;
}
D
Esimerkki D-kielellä
tuonti std . stdio ;
abstrakti luokka Kuva
{
suojatun merkkijonon nimi ;
merkkijono getInfo ();
}
class Tyhjä : Kuva
{
ohitusmerkkijono getInfo ( ) { return null ; } }
luokka Ympyrä : Kuva
{
suojattu Kuviokuva ; _
tämä ( kuva f )
{
kuva = f ;
nimi = "ympyrä" ;
}
ohittaa merkkijono getInfo ()
{
return name ~ figure . getInfo ();
}
}
luokka Pylväs : Kuva
{
suojattu Kuviokuva ; _
tämä ( kuva f )
{
kuva = f ;
nimi = "baari" ;
}
ohitusmerkkijono getInfo ( ) { return figure . getInfo () ~ nimi ; } }
void main ()
{
Kuvaluvut = uusi palkki ( uusi ympyrä ( uusi pylväs ( uusi ympyrä ( uusi Tyhjä ( )))));
writeln ( figures.getInfo ( ) ); }
Python
Alla on esimerkki suunnittelumallin toteutuksesta. Pythonissa on funktion ja luokan sisustajia , joilla on erilainen konsepti kuin suunnittelukuvio.
Python-esimerkki
[1]
"""
Demonstroidut sisustajat maailmassa, jossa on 10x10 arvoruudukko 0-255.
"""
tuonti satunnaisesti
def s32_to_u16 ( x ):
jos x < 0 :
merkki = 0xf000
else :
merkki = 0
alaosa = x & 0x00007ffff
palauta alas | merkki
def siemen_from_xy ( x , y ): paluu s32_to_u16 ( x ) | ( s32_to_u16 ( y ) << 16 )
luokka RandomSquare :
def __init__ ( s , seed_modifier ):
s . siemen_muokkaus = siemen_muokkaus
def get ( s , x , y ):
siemen = siemen_from_xy ( x , y ) ^ s . seed_modifier
satunnainen . siemen ( seed )
return satunnainen . randint ( 0 , 255 )
luokka DataSquare :
def __init__ ( s , alkuarvo = Ei mitään ):
s . data = [ alkuarvo ] * 10 * 10
def get ( s , x , y ):
palauttaa s . data [ ( y * 10 ) + x ] # kyllä: nämä ovat kaikki 10x10
def set ( s , x , y , u ):
s . data [ ( y * 10 ) + x ] = u
luokka CacheDecorator :
def __init__ ( s , koristeltu ):
s . koristeltu = koristeltu
s . välimuisti = DataSquare ()
def get ( s , x , y ):
jos s . välimuisti . get ( x , y ) == Ei mitään :
s . välimuisti . asettaa ( x , y , s . koristeltu . saada ( x , y ) )
paluu s . välimuisti . saada ( x , y )
luokka MaxDecorator :
def __init__ ( s , koristeltu , max ):
s . koristeltu = koristeltu
s . max = max
def get ( s , x , y ):
jos s . koristeltu . saada ( x , y ) > s . max :
paluu s . max
tuotto s . koristeltu . saada ( x , y )
luokka MinDecorator :
def __init__ ( s , koristeltu , min ):
s . koristeltu = koristeltu
s . min = min
def get ( s , x , y ):
jos s . koristeltu . saada ( x , y ) < s . min :
paluu s . min
palautus s . koristeltu . saada ( x , y )
luokka VisibilityDecorator :
def __init__ ( s , koristeltu ):
s . koristeltu = koristeltu
def get ( s , x , y ):
palauta s . koristeltu . get ( x , y )
def draw ( s )
: y alueella ( 10 ) : x alueella ( 10 ) : tulosta " % 3d " % s . hanki ( x , y ), tulosta
# Rakenna nyt sisustussuunnittelijoiden putki:
random_square = RandomSquare ( 635 )
random_cache = CacheDecorator ( satunnainen_neliö )
max_filtered = MaxDecorator ( random_cache , 200 )
min_filtered = MinDecorator ( max_filtered , 100 )
final = VisibilityDecorator ( min_filtered )
lopullinen . piirtää ()
Tulos (huomaa pseudosatunnaislukugeneraattorin käyttö):
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 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 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 1001
PHP
PHP esimerkki
abstrakti luokka AbstractComponent
{
abstrakti julkinen toiminto ( );
}
luokka ConcreteComponent laajentaa AbstractComponent
{
julkisen funktion toiminta ()
{
// ...
}
}
abstrakti luokka AbstractDecorator expands AbstractComponent
{
suojattu $komponentti ;
public function __construct ( AbstractComponent $komponentti )
{
$this -> komponentti = $komponentti ;
}
}
class ConcreteDecorator laajentaa AbstractDecorator
{
julkisen funktion toiminta ()
{
// ... laajennettu toiminnallisuus ...
$this -> komponentti -> toiminta ();
// ... laajennettu toiminnallisuus ...
}
}
$decoratedComponent = uusi ConcreteDecorator (
uusi ConcreteComponent ()
);
$decoratedComponent -> operaatio ();
PHP 5
Yleisimmin käytetty PHP5-esimerkki
<?php
käyttöliittymä IText
{
julkinen toiminto näyttää ();
}
class TextHello toteuttaa IText
{
suojattu $objekti ;
public function __construct ( IText $teksti ) {
$this -> object = $teksti ;
}
julkinen toimintoshow () { echo ' Hei' ; $this -> object -> show (); } }
class TextWorld toteuttaa IText
{
suojattu $objekti ;
public function __construct ( IText $teksti ) {
$this -> object = $teksti ;
}
julkinen toiminto näytä () {
echo 'maailma' ;
$this -> object -> show ();
}
}
class TextSpace toteuttaa IText
{
suojattu $objekti ;
public function __construct ( IText $teksti ) {
$this -> object = $teksti ;
}
julkinen toiminto show () {
echo ' ' ;
$this -> object -> show ();
}
}
luokka TextEmpty toteuttaa ITextin
{
julkinen funktio näytä () {
}
}
$decorator = uusi TextHello ( uusi TextSpace ( uusi TextWorld ( uusi TextEmpty ())));
$decorator -> show (); // Hello world
echo '<br />' . PHP_EOL ;
$decorator = uusi TextWorld ( uusi TextSpace ( uusi TextHello ( uusi TextEmpty ())));
$decorator -> show (); // Hei maailma
CoffeeScript
Esimerkki CoffeeScriptistä
# Komponenttiluokan
Notebook # Markkinointihinta :
500 # $
# Tekniset tiedot
hdd: 320 # GB
ram: 4 # GB
ydin: 'i5 2.3' # GHz
# Sisustusluokka
NovaNotebook rakentaja : (tuote) -> @hinta
= tuote . hinta * 1.3
# Sisustusluokka
ImportNotebook rakentaja : (tuote) -> @hinta
= tuote . hinta * 1,5
# Sisustusluokan
AppleNotebook rakentaja : (tuote) -> @hinta
= tuote . hinta * 2.1
macBookInRussia = uusi ImportNotebook uusi NovaNotebook uusi AppleNotebook uusi Notebook -
konsoli . loki ( macBookInRussia .price ) _
JavaScript
JavaScript esimerkki
Sisustuskuviota dynaamisesti kirjoitetuilla kielillä voidaan käyttää ilman rajapintoja ja perinteistä OOP-perintöä.
Tämä esimerkki on kopioitu artikkelin englanninkielisestä versiosta. Kahvin hinnan laskeminen:
// ConcreteComponent (luokka koristella myöhemmin)
function Kahvi () {
this . hinta = funktio () {
paluu 1 ;
};
}
// Decorator A-
toiminto Maito ( kahvi ) {
this . hinta = funktio () {
paluu kahvi . hinta () + 0,5 ;
};
}
// Sisustus B -
toiminto Piiska ( kahvi ) {
this . hinta = funktio () {
paluu kahvi . hinta () + 0,7 ;
};
}
// Decorator C
-toiminto Sprinkles ( kahvi ) {
this . hinta = funktio () {
paluu kahvi . hinta () + 0,2 ;
};
}
// Voidaan käyttää näin:
var kahvi = uusi Maito ( uusi Piiska ( uusi Sprinkles ( uusi Kahvi ())));
hälytys ( kahvi.kustannus ( ) ) ;
// Tai enemmän visuaalisesti:
var coffee = new Coffee ();
kahvi = uusi Sprinkles ( kahvi );
kahvi = uusi Piiska ( kahvi );
kahvi = uusi Maito ( kahvi );
hälytys ( kahvi.kustannus ( ) );
Yllä olevan C#-esimerkin toteutus. ConcreteComponentiin on lisätty paikallinen muuttuva hinta, joka muuttuu sekä itsessään että sisustajissa. Luokkien nimet (paitsi jälkiliitteet "A" ja "B") ovat samat kuin mallin jäsenten nimet.
function Komponentti () {
tämä . operaatio = funktio () { };
tämä . getPrice = funktio () { };
tämä . setPrice = funktio () { };
}
function ConcreteComponent () {
var price = 10 ;
tämä . operaatio = funktio () {
hinta += 4 ;
hälytys ( "ConcreteComponent. toiminta, hinta: " + hinta );
};
tämä . getPrice = function ( ) {
palautushinta ; }; tämä . setPrice = funktio ( val ) { hinta = val ; }; } ConcreteComponent . prototyyppi = uusi Komponentti (); ConcreteComponent . prototyyppi . konstruktori = ConcreteComponent ;
function Sisustaja () {
var komponentti ;
tämä . setComponent = funktio ( val ) {
komponentti = arvo ;
};
tämä . getComponent = funktio ( ) {
paluukomponentti ; }; tämä . operaatio = funktio () { komponentti . operaatio (); }; tämä . getPrice = function ( ) { paluukomponentti . hanki hinta (); }; tämä . setPrice = function ( val ) { komponentti . setprice ( val ); }; } Sisustaja . prototyyppi = uusi Komponentti (); Sisustaja . prototyyppi . rakentaja = sisustaja ;
function ConcreteDecoratorA () {
Sisustaja . soita ( tämä );
var toiminta = tämä . toiminta ; // viittaus Decoratorissa määriteltyyn menetelmään
tämä . operaatio = funktio () {
tämä . setPrice ( tämä . getPrice () + 3 );
hälytys ( "ConcreteDecoratorA. toiminta, hinta: " + tämä . getPrice ());
operaatio ();
};
}
function ConcreteDecoratorB () {
var duplicate = this ; // viittaus instantoituun objektiin (koska tämä voi muuttua)
Decorator . soita ( tämä );
var toiminta = tämä . toiminta ; // viittaus Decoratorissa määriteltyyn menetelmään
tämä . operaatio = funktio () {
tämä . setPrice ( this.getPrice ( ) + 1 ) ; hälytys ( "ConcreteDecoratorB. toiminta, hinta: " + tämä . getPrice ()); lisättyKäyttäytyminen (); operaatio (); };
function addedBehavior () {
kaksoiskappale . setPrice ( kaksoiskappale . getPrice ( ) + 2 );
hälytys ( "addedBehavior, hinta: " + kaksoiskappale . getPrice ());
}
}
// käyttö
c = uusi ConcreteComponent ();
d1 = uusi ConcreteDecoratorA ();
d2 = uusi BetoninkoristelijaB ();
hälytys ( "alkuperäinen hinta: " + c . getPrice ()); // kymmenen
d1 . setComponent ( c );
d2 . setComponent ( d1 );
d2 . operaatio ();
alert ( "hinta muuntamisen jälkeen: " + c . getPrice ()); // kaksikymmentä
VB.NET
Esimerkki: VB.NET
Nimitilan sisustaja
luokan ohjelma
Jaettu alapää () ' Luo ConcreteComponent ja kaksi koristelua Dim C Uutena ConcreteComponentina ( ) Dim D1 Uutena ConcreteDecoratorA ( ) Dim D2 Uutena ConcreteDecoratorinaB ( )
' Sisustajaviitteet
D1 . Aseta komponentti ( C )
D2 . SetComponent ( D1 )
D2 . operaatio ()
Odotetaan käyttäjäkonsolin
toimintoja . Lue ()
End Sub
loppuluokka _
'''' <summary>
'''' Komponentti - komponentti
''' </summary>
''' <remarks>
''' <li>
''' <lu>määritä käyttöliittymä objekteille, jotka voidaan määrittää dynaamisesti
''' lisävastuut;</lu>
''' </li> ''' </
remarks >
MustInherit Class Component
Public MustOverride Sub Operation ()
Loppuluokka
'''' <summary>
'''' ConcreteComponent - betonikomponentti
''' </summary>
''' <remarks>
''' <li>
''' <lu>määrittää objektin, jolla on lisävastuita</lu>
' '' </li>
'''' </remarks>
Luokka ConcreteComponent
perii komponentin
Julkinen ohittaa alitoiminnot ( ) Konsoli . WriteLine ( "ConcreteComponent.Operation()" ) End Sub End Class
'''' <summary>
'''' Sisustaja - sisustaja
''' </summary>
''' <huomautukset>
''' <li>
''' <lu> tallentaa viittauksen objektiin <katso cref="komponentti" /> ja määrittää rajapinnan
'''', joka vastaa käyttöliittymää <katso cref="komponentti"/></lu>
' '' </li>
''' </remarks>
MustInherit Class Decorator
perii komponentin
suojatun komponentin komponenttina
Public Sub SetComponent ( ByVal - komponentti Komponenttina ) Me . komponentti = komponentti End Sub
Julkinen ohittaa alitoiminnon ( )
Jos komponentti ei ole mitään , komponentti
. Toiminta () End If End Sub End Class
'''' <summary>
'''' ConcreteDecorator – betonisisustaja
''' </summary>
''' <remarks>
''' <li>
''' <lu>asettaa komponentille lisävastuita.</lu>
'' </li> ''' </
remarks >
Luokka ConcreteDecoratorA
perii sisustaja
Yksityinen lisätty Tila merkkijonona
Julkinen ohittaa alitoiminnon ( ) MyBase . Operation () addedState = "Uusi tila" -konsoli . WriteLine ( "ConcreteDecoratorA.Operation()" ) End Sub End Class
' "Concrete DecoratorB"
Luokka ConcreteDecoratorB
perii sisustajan
Julkinen ohittaa alitoiminnon ( ) MyBase . Käyttö () LisättyKäyttäytyminen () Konsoli . WriteLine ( "ConcreteDecoratorB.Operation()" ) End Sub
Yksityinen Sub AddedBehavior ()
End Sub
End Class
End Namespace
Delphi
Delphi- ja Free Pascal -tukiluokkaapulaiset , jotka tekevät koristelukuvion käytöstä tarpeetonta .
Delphi esimerkki
ohjelma NoMoreDecorators ;
tyyppi
TMyObject = luokkamenettely
WriteHello ; _ loppu ;
TMyObjectHelper = TMyObject - menettelyn luokan apuohjelma WriteHello ( const Nimi : merkkijono ) ; ylikuormitus ; loppu ;
menettely TMyObject . Kirjoita Hei ;
begin
writeln ( 'Hei' ) ;
loppu ;
menettely TMyObjectHelper . WriteHello ( const Nimi : merkkijono ) ;
begin
writeln ( 'Hei, ' , Nimi , '!' ) ;
loppu ;
var
o : TMyObject ;
begin
o := TMyObject . luoda ;
o . Kirjoita Hei ;
o . WriteHello ( 'farkku' ) ;
o . Ilmainen ;
loppua .
Delphi esimerkki
ohjelma DecoratorPattern ;
{$APPTYPE CONSOLE}
käyttää
SysUtilsia ;
tyyppi
TInterfaceComponent = luokka
julkinen
menettely Operaatio ; virtuaalinen ; abstrakti ;
loppu ;
tyyppi
TConcreteComponent = luokka ( TInterfaceComponent )
julkinen
menettely Operaatio ; ohittaa ;
loppu ;
menettely TConcreteComponent . toiminta ;
begin
Write ( 'ei voi' ) ;
loppu ;
tyyppi
TDecorator = luokka ( TInterfaceComponent )
yksityinen
FComponent : TInterfaceComponent ;
julkinen
konstruktori Luo ( aComponent : TInterfaceComponent ) ;
loppu ;
rakentaja TDecorator . Luo ( aComponent : TInterfaceComponent ) ;
begin
FComponent := aComponent ;
loppu ;
tyyppi
TBeforeDecorator = luokka ( TDecorator )
julkinen
menettely Toiminta ; ohittaa ;
loppu ;
menettely TBeforeDecorator . toiminta ;
begin
Write ( 'Suorita,' ) ;
FComponent . toiminta ;
loppu ;
tyyppi
TAfterDecorator = luokka ( TDecorator )
julkinen
menettely Toiminta ; ohittaa ;
loppu ;
menettely TAfterDecorator . toiminta ;
aloita
FComponent . toiminta ;
Kirjoita ( 'anteeksi' ) ;
loppu ;
tyyppi
TOverrideDecorator = luokka ( TDecorator )
julkinen
menettely Toiminta ; ohittaa ;
loppu ;
menettely TOverrideDecorator . toiminta ;
begin
Write ( 'Rakastakaa toisianne!' ) ;
loppu ;
var
vSameComponent : TInterfaceComponent ;
begin
vSameComponent := TAfterDecorator . Luo ( TConcreteComponent . Create ) ;
vSameComponent . toiminta ; // Tulostaa "ei voi anteeksi"
Writeln ;
vSameComponent := TBeforeDecorator . Luo ( vSameComponent ) ;
vSameComponent . toiminta ; // Tulostaa "Execute, can't pardon"
Writeln ;
vSameComponent := TOverrideDecorator . Luo ( vSameComponent ) ;
vSameComponent . toiminta ; // Tulostaa "Rakasta toisianne!"
// Yksinkertaisuuden vuoksi esineiden tuhoamista ei näytetä
Readln ;
loppua .
Swift
Nopea esimerkki
protokolla Kirja {
var title : String { get set }
var price : Int { get set }
func getPrice () -> Int
}
luokka BookImpl : Kirja {
var title : String = ""
var price : Int = 1000
func getPrice () - > Int {
paluuhinta }
}
luokan alennuskirja : Kirja {
let element : BookImpl
var title : String = "Groaming-algoritmit"
var price : Int = 0
init ( elementti : BookImpl ) {
itse . elementti = elementti
itse . otsikko = elementti . nimi
itse . hinta = elementti . hinta
}
// 30 %
alennus func getPrice () -> Int {
paluuhinta - ( hinta * 30 ) / 100 }
}
// Käytä koristelua
anna kirja = BookImpl ()
anna alennusKirja = AlennusKirja ( elementti : kirja )
tulosta ( alennusKirja . getPrice ())
Kirjallisuus
- Alan Shalloway, James R. Trott. Suunnittelumalleja. Uusi lähestymistapa olio-suuntautuneeseen suunnitteluun = Design Patterns Explained: A New Perspective on Object-Oriented Design. - M . : "Williams" , 2002. - S. 288. - ISBN 0-201-71594-5 .
- Eric Freeman, Elizabeth Freeman. Suunnittelukuviot = Head First Design Patterns. - Pietari. : Peter. — 656 s. - ISBN 978-5-459-00435-9 .
Muistiinpanot
- ↑ Sisustuskuvio . wiki.python.org . Haettu 24. lokakuuta 2021. Arkistoitu alkuperäisestä 24. lokakuuta 2021. (määrätön)
Linkit