Stáhnout prezentaci
Prezentace se nahrává, počkejte prosím
ZveřejnilMarcel Čech
1
Decorator
2
Rozšiřuje objekty o dodatečné chování rozšiřuje konkrétní objekty, ne třídy rozšiřuje objekt dynamicky, tj. za běhu Upřednostňuje kompozici objektů před dědičností Delegace volání na dekorovaný objekt + vlastní přidaná funkcionalita vlastní přidané chování může být před i za delegovaným voláním Decorator – o čem to je
3
Motivační příklad – GUI Toolkit GUI Toolkit obsahuje komponentu TextView prosté zobrazení textu Chceme instance této komponenty „dekorovat“ přidat posuvník přidat rámeček apod. Hodilo by se přitom: mít k dispozici také původní TextView bez dekorací kombinovat vlastnosti mezi sebou posuvník + rámeček přidávat některé vlastnosti vícenásobně dvojitý rámeček přidávat/odebírat konkrétní vlastnosti za běhu
4
1. pokus o řešení: „supertřída“ obsahuje stavy (flagy) pro všechny možné dekorace vykreslovací metoda kontroluje přítomnost jednotlivých dekorací Motivační příklad – GUI Toolkit class TextView { public void Draw() { /* Main drawing logic here. */ if (isBordered) { /* Border drawing logic here. */ } if (isScrollable) { /* Scrollbar drawing logic here. */ } private bool isBordered;// Is TextView bordered? private int borderWidth;// Used only by bordered TextViews. private bool isScrollable;// Is TextView scrollable? private int scrollBarPosition;// Used only by scrollable TextViews. }
5
1. pokus o řešení: „supertřída“ můžeme instancím přidávat/odebírat vlastnosti za běhu nemusíme dekorovat vůbec můžeme kombinovat vlastnosti netřeba rozlišovat mezi obyčejnou a dekorovanou instancí nemůžeme jednu vlastnost použít vícekrát instance ví, že je dekorována silně neflexibilní řešení nerozšiřitelné bez modifikace TextView Motivační příklad – GUI Toolkit
6
2. pokus o řešení: dědičnost bázová třída – TextView odvozené – BorderedTextView, ScrollableTextView, BorderedScrollableTextView Motivační příklad – GUI Toolkit class TextView { public void Draw() {... } } class BorderedTextView extends TextView { public void Draw() {... } } class ScrollableTextView extends TextView { public void Draw() {... } } class BorderedScrollableTextView extends ScrollableTextView { public void Draw() {... } }
7
2. pokus o řešení: dědičnost statické nemožno měnit vlastnosti instance za běhu pro každou kombinaci vlastností je třeba vytvořit novou třídu BorderedScrollableBorderedTextView... vede k explozi tříd (n vlastností → 2 n tříd) podstatně zvyšuje komplexitu systému Motivační příklad – GUI Toolkit
8
3. pokus o řešení: Decorator Motivační příklad – GUI Toolkit Reference na dekorovaný objekt Společný (abstraktní) předek – def. interface pro kreslení Delegace vykreslování na dekorovaný objekt Konkrétní vizuální komponenta Konkrétní dekorátory vyjma delegace implementují navíc své vlastní vykreslování Konkrétní dekorátor Abstraktní dekorátor
9
3. pokus o řešení: Decorator Motivační příklad – GUI Toolkit public interface VisualComponent { public void Draw(); } class TextView implements VisualComponent { public void Draw() { // draw window } abstract class Decorator implements VisualComponent { protected VisualComponent vc; // component being decorated public Decorator(VisualComponent vc) { this.vc = vc; } public void Draw() { vc.draw(); //delegation } class ScrollDecorator extends Decorator { public ScrollDecorator(VisualComponent vc) { super(vc); } @Override public void Draw() { super.Draw(); // draw component drawScrollBar(); // draw scrollbar } private void drawScrollBar() {...} private int scroll_position; public void ScrollTo(int pos) { scroll_position = pos; } class BorderDecorator extends Decorator {... }
10
3. pokus o řešení: Decorator dekorátory přidávají jednotlivé vlastnosti (dekorace) můžeme instancím přidávat/odebírat vlastnosti za běhu máme k dispozici i obyčejný TextView dekorace jsou navzájem nezávislé lze je libovolně kombinovat lze je používat i vícekrát je to transparentní z hlediska klienta není rozdíl mezi obyčejným a dekorovaným TextView TextView o dekoracích vůbec neví Motivační příklad – GUI Toolkit VisualComponent window = new BorderDecorator( new ScrollDecorator( new TextView())); window.Draw();
11
Účastníci: Component – def. rozhraní pro objekty, které je možné dynamicky rozšiřovat ConcreteComponent – def. objekt, který je možné dynamicky rozšířit Decorator – def. rozhraní pro všechny dekorátory obsahuje refenci na objekt, který dekoruje všechna volání deleguje na dekorovaný objekt ConcreteDecorator – přidává dodatečné chování komponentě Decorator – struktura a účastníci
12
Výhody vyšší flexibilita pro přidávání funkcionality než při statickém dědění vlastnosti lze přidávat/odebírat za běhu aplikace několikanásobné použití stejné dekorace transparentnost „pay-as-you-go“ není třeba předvídat všechny potřeby klienta jednoduché inkrementální přidávání funkcionality Nevýhody komponenta a její dekorovaná verze nejsou identické dekorátor se chová jako transparentní zapouzdření při použití dekorátorů nespoléhat na identitu objektů! mnoho podobných (malých) objektů potenciálně horší orientace v kódu Decorator – výhody a nevýhody
13
Použití typicky pomocí řetězení konstruktorů: Rozhraní dekorátoru musí být shodné s rozhraním dekorovaného objektu dědění od společného předka nebo implementace společného interface Abstraktní dekorátor lze vynechat za předpokladu, že potřebujeme přidat pouze jediné rozšíření často v případě, kdy potřebujeme rozšířit existující kód delegování na komponentu se pak děje přímo v tomto jediném dekorátoru Společný předek (Component) by měl zůstat odlehčený definice rozhraní, nikoli uložení dat jinak hrozí, že dekorátory budou příliš těžkotonážní Dobré zvážit, zda měnit povrch objektu, či jeho vnitřnosti návrhový vzor Strategy Decorator – implementace Component c = new ConcreteDecoratorA( new ConcreteDecoratorB( new ConcreteComponent(...))); c.Operation();
14
Grafické toolkity X Windows System Java Swing System.Windows.Controls Čtení vstupu, zapisování výstupu System.IO.Stream java.io Reálně využívané Decoratory Component ConcreteComponent Decorator ConcreteDecorator DataInputStream dis = new DataInputStream( new GzipInputStream( new BufferedInputStream( new FileInputStream("file.gz")))); dis.Read(...);
15
Adapter Decorator mění pouze chování objektu, ne jeho rozhraní Adapter dá objektu zcela nové rozhraní Composite Decorator lze technicky vnímat jak zdegenerovaný Composite s jedinou komponentou Decorator přidává dodatečné chování není určen pro agregaci objektů Strategy Decorator umožňuje měnit skin (povrch, kůži...) objektu v zásadě obaluje nějaký objekt a mění při tom jeho chování zatímco Strategy umožňuje měnit „vnitřnosti“ (guts) objektu komponenta ve Strategy ví o možných extenzích, u Decoratoru nikoli: Související vzory
Podobné prezentace
© 2024 SlidePlayer.cz Inc.
All rights reserved.