„Díszítő programtervezési minta” változatai közötti eltérés

[ellenőrzött változat][ellenőrzött változat]
Tartalom törölve Tartalom hozzáadva
KMBot (vitalap | szerkesztései)
a gondolatjel javítása (checkwiki [050]) AWB
Xqbot (vitalap | szerkesztései)
a Bot: Replace deprecated <source> tag and "enclose" parameter [https://lists.wikimedia.org/pipermail/wikitech-ambassadors/2020-April/002284.html]; kozmetikai változtatások
1. sor:
Az [[objektumorientált programozás]]ban (OOP) a '''díszítő programtervező minta''' egy olyan [[Programtervezési minták|programtervezési minta]], amely lehetővé teszi adott [[objektum]]okhoz más viselkedések hozzáadását akár statikusan, akár dinamikusan anélkül, hogy hatással lenne az azonos [[Osztály (számítástechnika)|osztályosztályból]]ból származó többi objektumra.<ref>{{cite book|last=Gamma, et. al.|first=Erich|title=Design Patterns|year=1995|publisher=Addison-Wesley Publishing Co, Inc.|location=Reading, MA|isbn=0-201-63361-2|pages=175ff}}</ref> A díszítő gyakran alkalmas arra is, hogy a program megfeleljen az egyértelmű felelősség elvének, mivel lehetővé teszi a felelősségek egyértelmű felosztását különböző osztályok között.<ref>{{cite web|title=How to Implement a Decorator Pattern |url=http://sam-burns.co.uk/57/how-to-implement-a-decorator-pattern/ |deadurl=yes |archiveurl=https://web.archive.org/web/20150707165957/http://sam-burns.co.uk/57/how-to-implement-a-decorator-pattern/ |archivedate=2015-07-07 |df= }}</ref>
 
== Bevezetés ==
[[Fájl:Decorator UML class diagram.svg|thumbbélyegkép|rightjobbra|400px|Díszítő minta [[Unified Modeling Language|UML]] osztály diagramja]]
A díszítő minta arra használható, hogy kiterjeszthető legyen (díszítés) számos objektum funkcionalitása statikusan vagy néhány esetben [[futási idő (program életciklusának fázisa)|futási időben]], függetlenül más azonos [[Osztály (számítástechnika)|osztályhoz]] tartozó példányoktól, mindehhez alapozást nyújtva tervezési időben.
Mindez megvalósítható egy új ''díszítő'' osztály tervezésével, amely [[becsomagolás|becsomagolbecsomagolja]]ja az eredeti osztályt. A becsomagolás megvalósítható a következő lépések sorozatával:
# hozzunk létre egy "díszítő" osztályt az eredeti "komponens" alosztályaként (lásd az UML diagramot);
# a díszítő osztályban adjunk hozzá egy komponens referenciát mezőként;
19. sor:
A díszítő minta alternatívája az [[alosztály (informatika)|alosztályok képzésének]]. Az alosztályok képzésével viselkedések adhatók hozzá [[fordítási idő]]ben, és a változás kihat az eredeti osztály összes példányára, míg a díszítő minta használatával [[futási idő (program életciklus fázis)|futási időben]] biztosítható új viselkedés egyéni objektumok számára.
 
Ez a különbség akkor válik nagyon fontossá, amikor sokféle ''független'' módon lehetséges a funkcionalitás kiterjesztése. Néhány [[objektumorientált programozás|objektumorientált programozási nyelvben]] az osztályok létrehozása futási időben nem lehetséges, és tipikusan nem lehetséges megjósolni tervezési időben, hogy a kiterjesztések milyen kombinációjára lesz szükség később. Ez azt jelentené, hogy egy új osztálynak el kéne készíteni az összes lehetséges kombinációját. Ezzel szemben a díszítők objektumok, melyek futási időben jönnek létre, kombinálhatók használat előtt. Az I/O folyamok megvalósítása mind a [[Java Platform, Standard Edition#java.io|Java]]-ban, mind a [[.NET keretrendszer]]ben alkalmazza a díszítő mintát.
 
== Motiváció ==
[[Fájl:UML2 Decorator Pattern.png|thumbbélyegkép|400px|Windows példa UML Diagramja]]
Példaként vegyünk egy ablakot egy [[ablakozó rendszerben]]. Ahhoz, hogy egy ablak tartalmát [[görgetés|görgetni]] tudjuk, szükség lehet arra, hogy megfelelő vízszintes ill. függőleges [[görgetősáv]]ot adjunk hozzá. Tegyük fel, hogy az ablakokat a ''Window'' osztály példányai reprezentálják, és tegyük fel, hogy ennek az osztálynak nem létezik görgetősáv hozzáadás funkcionalitása. Készíthetünk alosztályt ''ScrollingWindow'' néven, amely ellátja ezt a feladatot, vagy készíthetünk egy ''ScrollingWindowDecorator''-t, amely hozzáadja ezt a funkcionalitást a létező ''Window'' objektumokhoz. Ezen a ponton, bármelyik megoldás megfelelő lenne.
 
30. sor:
 
Egy másik jó példa, ahol a díszítő használata kívánatos lehet, pl. ha egy objektum tulajdonságainak, ill. metódusainak az elérését korlátozni szükséges néhány szabály halmaz szerint, vagy esetleg számos párhuzamosan használt szabály halmaz szerint (pl. különböző felhasználói hitelesítések esetén, stb.). Ebben az esetben az eredeti objektumban az elérések szabályozásának megvalósítása helyett az változatlanul hagyható, és bárminemű korlátozástól mentesen használható. Az eredeti objektum becsomagolható egy elérést szabályozó díszítő objektumba, amely kizárólagosan szolgálhatja ki az eredeti objektum interfészének egy megengedett részhalmazát.
== Használata ==
A díszítő lehetővé teszi a viselkedés futásidejű hozzáadását. Ha számítani kell a többalakúságra (polimorfizmus), és még egy interfészt kell figyelembe venni, akkor az [[illesztő programtervezési minta]] használható; ha pedig le kell egyszerűsíteni a viselkedést, akkor a [[homlokzat programtervezési minta]] jelenthet segítséget.<ref>{{cite journal | last1 = Freeman | first1 = Eric | authorlink1 = | last2 = Freeman | first2 = Elisabeth | authorlink2 = | last3 = Sierra | first3 = Kathy | authorlink3 = | last4 = Bates | first4 = Bert | authorlink4 = | editor1-last = Hendrickson | editor1-first = Mike | editor-link1 = | editor2-last = Loukides | editor2-first = Mike | editor-link2 = | year = 2004 | title = Head First Design Patterns | volume = 1 | pages = 243, 252, 258, 260 | publisher = O'Reilly | format = paperback | isbn = 978-0-596-00712-6 | accessdate = 2012-07-02 | url = https://www.goodreads.com/book/show/58128.Head_First_Design_Patterns
}}</ref>
 
== Példák ==
<!-- Wikipedia is not a list of examples. Do not add examples from your favorite programming language here; this page exists to explain the design pattern, not to show how it interacts with subtleties of every language under the sun. Feel free to add examples here: http://en.wikibooks.org/wiki/Computer_Science_Design_Patterns/Decorator -->
 
=== Java ===
 
==== Első példa (ablak/görgetés esete) ====
A következő Java példa illusztrálja a díszítők használatát az ablak/görgetés esetén.
<sourcesyntaxhighlight lang="java">
// a Window interfész osztály
public interface Window {
58. sor:
}
}
</syntaxhighlight>
</source>
 
A következő osztályok díszítőket tartalmaznak az <tt>Window</tt> osztályhoz, beleértve a díszítő osztályokat magukat is.
 
<sourcesyntaxhighlight lang="java">
// absztrakt díszítő osztály, amely megvalósítja a Window interfészt
abstract class WindowDecorator implements Window {
121. sor:
}
}
</syntaxhighlight>
</source>
 
Íme a teszt program, ami létrehoz egy olyan <tt>Window</tt> példányt, amely teljesen díszített (azaz vízszintes és függőleges görgetősávval rendelkezik), és kiírja a leírásukat:
 
<sourcesyntaxhighlight lang="java">
public class DecoratedWindowTest {
public static void main(String[] args) {
136. sor:
}
}
</syntaxhighlight>
</source>
 
Ezen program kimenete a következő: "simple window, including vertical scrollbars, including horizontal scrollbars". Figyeljük meg, hogy a <tt>getDescription</tt> metódusa a két díszítőnek először visszaadja a díszített <tt>Window</tt> leírását, és azt díszíti egy utótaggal.
 
==== Második példa (kávékészítés esete) ====
A következő Java példa a díszítők használatát szemlélteti a kávékészítés esetén. Ebben a példában az esetünk csak a költségeket és a hozzávalókat tartalmazza.
{{Clear}}
<sourcesyntaxhighlight lang="java">
// The abstract Coffee class defines the functionality of Coffee implemented by decorator
public abstract class Coffee {
160. sor:
}
}
</syntaxhighlight>
</source>
 
A következő osztályok tartalmazzák a díszítőket az összes <tt>Coffee</tt>(kávé) osztályra, beleértve a díszítő osztályokat magukat.
 
<sourcesyntaxhighlight lang="java">
 
// absztrakt díszítő osztály, amely kiterjeszti a Coffee absztrakt osztályt
231. sor:
}
}
</syntaxhighlight>
</source>
 
Íme a tesztprogram, amely létrehoz egy <tt>Coffee</tt> példányt, amely teljes mértékben díszített (azaz tejjel, habbal, permettel) és kiszámolja kávé költségét és kiírja a hozzávalóit:
<sourcesyntaxhighlight lang="java">
public class Main {
256. sor:
}
</syntaxhighlight>
</source>
 
=== C++ ===
Következő példa program egy C++-os megvalósítás:
 
Include-ok
<sourcesyntaxhighlight lang="Cpp">
#include <iostream>
#include <string>
</syntaxhighlight>
</source>
 
Absztrakt alaposztályok
<sourcesyntaxhighlight lang="Cpp">
// Az absztrakt Coffee (kávé) osztály, amely definiálja a Coffee funkcionalitását, melyet a díszítő fog megvalósítani
struct Coffee {
276. sor:
};
inline Coffee::~Coffee(){}
</syntaxhighlight>
</source>
 
SimpleCoffee osztály.
<sourcesyntaxhighlight lang="Cpp">
// egy egyszerű kávé kiterjesztése extra hozzávalók nélkül
struct SimpleCoffee : Coffee {
290. sor:
}
};
</syntaxhighlight>
</source>
 
Díszítők
<sourcesyntaxhighlight lang="Cpp">
// Milk (tej) díszítő, amely tejet ad hozzá kávéhoz
332. sor:
};
 
</syntaxhighlight>
</source>
 
Tesztprogram
<sourcesyntaxhighlight lang="Cpp">
int main()
{
351. sor:
std::cout << "Cost: " << m2.getCost() << "; Ingredients: " << m2.getIngredients() << std::endl;
}
</syntaxhighlight>
</source>
 
A program kimenete:
362. sor:
</code>
 
=== Dinamikus nyelvek ===
A díszítő minta megvalósítható a dinamikus nyelvekkel, akár interfészekkel, akár OOP-ben hagyományos öröklődéssel.
 
== Kapcsolódó szócikkek ==
* [[Összetétel programtervezési minta]]
* [[Illesztő programtervezési minta]]
376. sor:
{{Jegyzetek}}
 
== További információk ==
* [http://c2.com/cgi/wiki?DecoratorPattern Decorator pattern description from the Portland Pattern Repository]
 
== Fordítás ==
{{fordítás|en|Decorator pattern|oldid=562517861}}