180 likes | 282 Vues
Implement the Visitor design pattern in a personnel system to handle payments, statistics, and taxes for different employee types. Learn how Visitor can define new operations without altering existing classes. Discover when to use Visitor and its advantages and disadvantages. Explore sample implementations using Java.
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