180 likes | 278 Views
Behavioral design patterns Visitor. Miroslav Sajko. Client. Person. payment() statistics() taxes(). FullTime. PartTime. Temporary. …. payment() statistics() taxes(). payment() statistics() taxes(). payment() statistics() taxes(). …. Modelová situácia.
E N D
BehavioraldesignpatternsVisitor Miroslav Sajko
Client Person payment() statistics() taxes() ... FullTime PartTime Temporary … payment() statistics() taxes() ... payment() statistics() taxes() ... payment() statistics() taxes() ... … Modelová situácia • Personálny systém – výplaty, dane, výkazy, ... • Viacrôznych typov – full/parttime, brigádnik, ... • Hierarchia tried –vykonávanie operácií nad nimi • Operácie v triedach – jednoducho, ale neflexibilne • Kód na 1 mieste – neprehľadné, switche, veľa if-ov
Visitor • Reprezentuj operáciu, ktorá sa má vykonať na elementoch v objektovej štruktúre. Vďaka Visitor-u možno definovať nové operácie bez nutnosti zmeny tried elementov nad ktorými Visitor operuje. • (Represent an operation to be performed on the elements of an objectstructure.Visitor lets you define a new operation without changing theclasses of the elements on whichitoperates.)
Visitor v UML • Visitor –deklaruje operáciu navštívenia pre každú triedu v štruktúre • ConcreteVisitor – implementuje každú operáciu deklarovanú Visitorom, kde každá operácia nová funkcionalita pre odpovedajúcu triedu objektu v štruktúre • Element– definuje operáciu prijatia Visitora, ktorá berie návštevníka ako argument • ConcreteElement – implem. túto operáciu prijatia návštevníka • ObjectStructure– môže byť composite alebo kolekcia, vie vymenovať svoje elementy a poskytuje high-level rozhranie, aby návštevník vedel navštíviť jeho elementy
Visitor visitFullTime(FullTime) visitPartTime(PartTime) PayWageVisitor TaxesVisitor visitFullTime(FullTime) visitPartTime(PartTime) visitFullTime(FullTime) visitPartTime(PartTime) Object structure (Traverser) Person accept(Visitor v) FullTime PartTime accept(Visitor v) accept(Visitor v) v.visitFullTime(this); v.visitPartTime(this); Modelová situácia
Pozorovania • Klient musí vytvoriť objekt ConcreteVisitora a potom ním pri prechádzaní štruktúrou navštevovať každý element • Element pri návšteve zavoláodpovedajúcu operáciuVisitora, element poskytuje sám seba (this) ako argument pre túto operáciu a tým umožní návštevníkovi pristupovať k stavu elementu
Dôsledky • Výhody: • Pridanie novej operácie na elemente je ľahké • Zhromažďovanie súvisiacich operácií na 1 miesto • Pri prechádzaní štruktúrou sa ukladá stav (kontext) priamo vo Visitorovi • Nevýhody: • Pridávanie elementov je náročné – nutná zmena všetkých Visitorov • Narušenie zapúzdrenia– Visitor potrebuje pristupovať k internému stavu tried • Zavedenie do hotového kódu je relatívne náročné
Kedy použiť vzor Visitor? • Objektová štruktúra obsahuje veľa rôznych tried s líšiacimi sa rozhraniami a chceme vykonávať operácie, ktoré závisia od konkrétnej triedy • Veľa vzdialených a nesúvisiacich operácií musí byť vykonaných nad objektami v štruktúre a nechceme „zašpiniť“ triedy operáciami • Triedy, ktoré definujú štruktúru sa menia zriedka, ale často sa menia a pridávajú operácie nad objektami
Implementácia • Kto je zodpovedný za prechádzanie štruktúrou? • Klient - pštrosí princíp • Štruktúra – Collection ľahko, Composite rekurzívne • Iterátor– elementy musia mať spoločného predka a kód na prechádzanie je na jednom mieste • Visitor – nemusia mať predka, dajú sa používať komplexnejšie algoritmy na prechod, nevýhodou je duplicita kódu vo Visitoroch
Implementácia • Single dispatchvs. Doubledispatch • Single - Operácia je vybraná na základe typu požiadavky a príjemcu • Double- Operácia je vybraná na základe typu požiadavky a dvoch príjemcov • Príklad: vykresľujeme geometrické tvary, pričom prieniky chceme kresliť inou farbou (2 parametre) • C, C++, C#, Javasú single; Perl, R doubledispatch • Dvojnásobnévolaniefunkcií (element.accept() a visitor.visit()) simulujefunkcionalitu Double dispatch
Sample public interface Person { public void accept(Visitor v); } public class FullTime implements Person { private int salary; private intworkedMonths; @Override public void accept(Visitor v) { v.visitFullTime(this); } public intgetSalary() { return salary; } public intgetWorkedMoths() { return workedMonths; } } public class PartTime implements Person { private inthourlyWage; private intworkedHours; @Override public void accept(Visitor v) { v.visitPartTime(this); } public intgetHourlyWage() { return hourlyWage; } public intgetWorkedHours() { return workedHours; } }
Sample public interface Visitor { public void visitFullTime(FullTime full); public void visitPartTime(PartTime part); } public class TaxesVisitor implements Visitor { private static final double FULL_TIME_TAX = 0.2; private static final double PART_TIME_TAX = 0.15; private double taxTotal = 0; @Override public void visitFullTime(FullTime full) { taxTotal += FULL_TIME_TAX * (full.getSalary() * full.getWorkedMoths()); } @Override public void visitPartTime(PartTime part) { taxTotal += PART_TIME_TAX * (part.getHourlyWage() * part.getHourlyWage()); } public double getTotal() { return taxTotal; } } public class Accounting { private List<Person> employees; public double getTotalTaxes() { TaxesVisitor visitor = new TaxesVisitor(); for (Person p: employees) { p.accept(visitor); } return visitor.getTotal(); } }
Využitie v praxi a súvisiace vzory • XML parsery – parser.parse(file, handler); startElement(), endElement(), character() • Stromové štruktúry – visitNode(), visitLeaf() • Súvisiace vzory: • Composite • Iterator
Zdroje • Design Patterns: Elements of Reusable Object-Oriented Software • http://userpages.umbc.edu/~tarr/dp/lectures/Visitor.pdf • http://ulita.ms.mff.cuni.cz/mff/sylaby/nprg024.html -> prezentácia Tomáša Soukupa
Ďakujem za pozornosťOtázky? Kontakt: miroslav.sajko@student.upjs.sk