Visitor Implementation CS 631: Visitor Implementation 7/1/2016 1

advertisement
Visitor Implementation
7/1/2016
CS 631: Visitor Implementation
1
Outline
• HW1 Analysis
– Question 1: Design
– Question 2: Implementation
– Question 3: Custom Application
• Visitor Implementation
– Basic Implementation
– Overloading and the Catch-All Function
– The Acyclic Visitor
7/1/2016
CS 631: Visitor Implementation
2
HW1: Market Simulator Design
7/1/2016
CS 631: Visitor Implementation
3
HW1: Classes
• Instrument: represents a simple financial instrument:
– Can be created with default parameters and be modified by parsing a
string using fromString() method.
• Market: a singleton to get current interest rates:
– Loaded from a file;
– Interpolation is used if the maturity specified in the getRate() method is
not in the maturities map.
• Valuation: a class to compute the value:
– Encapsulates a pointer to an instrument and returns it so that the
instrument can be modified;
– Uses the market object and the instrument attributes to calculate the
present value.
• MarketSimulation: a class to run the simulation:
– A static run() method takes names of the market and instruments files:
• Creates the market from a file, creates a valuation with an instrument, reads
instrument line by line; updates an instrument in the valuation; then
computes the present value.
7/1/2016
CS 631: Visitor Implementation
4
HW1: Implementation and Custom Application
• Implementation
– Use a SingletonHolder with policies to hold the Market
class;
– Implement the classes above;
– Ensure the program works correctly.
• Custom Application:
– Originality
– Proper use of design patterns
– Robust UML design
• Average grades:
– Q1: 8.3, Q2: 8.5, Q3: 8.6
7/1/2016
CS 631: Visitor Implementation
5
Basic Implementation: MarketSimulator
class MarketSimulator
{
public:
...
void run();{
for (each deal = // get a Deal object)
{
DealEvaluator eval(deal);
for (each trader = // get Trader object) {
trader->accept(eval);
double val=eval.getValue();
// find the trader (best_trader) for whom the
// deal has the maximum value
}
DealMaker maker(deal);
best_trader->accept(maker);
}}
...
7/1/2016
CS 631: Visitor Implementation
6
Basic Implementation: Trader
class Trader
{
public:
virtual void accept(TraderVisitor&) = 0;
...
};
class Hedger : public class Trader
{
...
virtual void accept(TraderVisitor& v)
{
v.visitHedger(*this);
}
}
...
7/1/2016
CS 631: Visitor Implementation
7
Basic Implementation: TraderVisitor
class TraderVisitor
{
public:
virtual void visitHedger(Hedger&) = 0;
virtual void visitSpeculator(Speculator&) = 0;
virtual void visitArbitrageur(Arbitrageur&) = 0;
...
};
class DealEvaluator : public class TraderVisitor
{
virtual void visitHedger(Hedger&)
{
// evaluate market conditions
// evaluate hedging strategy
// assign value
} ...
}
7/1/2016
CS 631: Visitor Implementation
8
Basic Implementation: DealMaker
class DealMaker : public class TraderVisitor
{
virtual void visitSpeculator(Speculator&)
{
// execute a deal using the speculating
// strategy
// update the capital data
// update all positions
}
virtual void visitArbitrageur(Arbitrageur&)
{
// execute a deal using the arbitrage
// update the capital data
// update all positions
}
}
7/1/2016
CS 631: Visitor Implementation
9
Overloading and the Catch-All Function
// Make a cosmetic change to get rid of redundancy
// in function names
class TraderVisitor
{
public:
virtual void visit(Hedger&) = 0;
virtual void visit(Speculator&) = 0;
virtual void visit(Arbitrageur&) = 0;
...
};
// It is now simpler to define all accept()
// functions
void Hedger::accept(TraderVisitor& v)
{
v.visit(*this);
}
7/1/2016
CS 631: Visitor Implementation
10
Cyclic Dependency
• Code dependency analysis
– For the Trader class definition to compile it needs to know
about TraderVisitor, because of accept functions.
– For the TraderVisitor class to compile it has to know about
all concrete Trader classes (Hedger, ...).
– This is called cyclic dependency.
• Cyclic Dependency
– Well-known maintenance bottlenecks.
– Trader needs TraderVisitor, and TraderVisitor needs the
whole Trader hierarchy. Hence Trader depends on its
subclasses.
– This is a cyclic name dependency:
• Class definitions depend only on their names to compile.
7/1/2016
CS 631: Visitor Implementation
11
Cyclic Dependency: Forward Declaration
// File TraderVisitor.h
class Trader;
class Hedger;
class Speculator;
class Arbitrageur;
...
class TraderVisitor
{
public:
virtual void visit(Hedger&) = 0;
virtual void visit(Speculator&) = 0;
virtual void visit(Arbitrageur&) = 0;
...
};
7/1/2016
CS 631: Visitor Implementation
12
Cyclic Dependency: Forward Declaration
(cont.)
// File Trader.h
class TraderVisitor;
class Trader
{
public:
virtual void accept(TraderVisitor&) = 0;
...
};
...
7/1/2016
CS 631: Visitor Implementation
13
Cyclic Dependency: Adding a New Trader
• Adding a new Trader type (say RiskTaker) leads to the
following:
– Add a new forward declaration in TraderVisitor.h
– Add a new pure overload to TraderVisitor class
• virtual void visit(RiskTaker&) = 0;
– Implement visit(RiskTaker&) for every concrete visitor
(DealEvaluator, DealMaker).
– Implement accept in the RiskTaker class.
• All Trader and TraderVisitor hierarchies will be
recompiled!
7/1/2016
CS 631: Visitor Implementation
14
The Acyclic Visitor
• Invented by Robert Martin in 1996.
• Leverages dynamic_cast to eliminate cyclicity.
• The approach
– Define a strawman base class, BaseVisitor. It does not have
any content.
– The visited hierarchy accepts a reference to BaseVisitor and
applied dynamic_cast to detect the a matching visitor.
– Once detected, the accept() function jumps from the visited
hierarchy to the visitor hierarchy.
7/1/2016
CS 631: Visitor Implementation
15
The Acyclic Visitor: TraderVisitor
class TraderVisitor
{
public:
// The do-nothing destructor ensures:
// (1) RTTI capabilities to apply dynamic_cast
// (2) Proper polymorphic destruction
virtual ~TraderVisitor() {}
};
// Define visitor for each concrete Trader
class HedgerVisitor
{
virtual void visit(Hedger&) = 0;
};
class SpeculatorVisitor ...
class ArbitrageurVisitor ...
7/1/2016
CS 631: Visitor Implementation
16
The Acyclic Visitor: Trader
void Hedger::accept(TraderVisitor& v)
{
if (HedgerVisitor* p =
dynamic_cast<HedgerVisitor*>(&v))
{
p->visit(*this);
}
else
{
... optionally call a catch-all function ...
}
}
7/1/2016
CS 631: Visitor Implementation
17
The Acyclic Visitor: DealEvaluator
class DealEvaluator :
public class TraderVisitor,
public class HedgerVisitor,
public class SpeculatorVisitor,
public class ArbitrageurVisitor
{
public:
void visit(Hedger& h)
{
...
}
void visit(Speculator& s) ...
void visit(Arbitrageur& a) ...
};
7/1/2016
CS 631: Visitor Implementation
18
The Acyclic Visitor: Order of Events
• Accume the following calls:
–
–
–
–
DealEvaluator eval;
Hedger* trader(...);
trader->accept(eval);
Order of events
• The eval object is converted to TraderVisitor.
• The virtual function Hedger::accept is called
• Hedger::accept attempts dynamic_cast<HedgerVisitor*> and
succeeds, because of multiple inheritance.
• Hedger::accept calls visit(Hedger&)
• The call reaches DealEvaluator::visit(Hedger&)
7/1/2016
CS 631: Visitor Implementation
19
The Acyclic Visitor: Dependencies
• Trader class definition depends on TraderVisitor by
name.
• HedgerVisitor, and others depend on concrete classes
of Trader respectively.
• The Hedger::accept implementation fully depends on
HedgerVisitor.
• Any concrete Visitor definition (DealEvaluator,
DealMaker) depends on TraderVisitor and all base
visitors.
7/1/2016
CS 631: Visitor Implementation
20
Download