Object Factory C++ Implementation CS 631: Object Factory 7/1/2016

advertisement
Object Factory
C++ Implementation
7/1/2016
CS 631: Object Factory
1
Outline
• Application
– Market Simulator
– Instrument Reader
– The Need for Object Factories
• Implementation
–
–
–
–
7/1/2016
Classes and Objects
Basic Implementation
Using Pointers to Functions
Generalization
CS 631: Object Factory
2
Market Simulator
• Market simulator may need to generate multiple trades
(instruments), evaluate such trades, and execute them.
• Assume instrument definitions are stored in a file.
Each instrument will be represented by different
format, for example:
– Forward contract (type, asset, maturity, delivery price)
• 1 GOLD 1 $100
– Bond (type, principal, maturity, coupon, period)
• 2 $100 10 0.6 0.5
• The main class will need to create different instrument
classes based on description.
7/1/2016
CS 631: Object Factory
3
Classes and Objects
// Instrument, Bond are classes; instrument is an object
// Classes are created by programmers; objects by the program
Instrument* instrument = new Bond(...);
// When classes are objects, they can be created at runtime.
// If C++ allowed it:
Class read(const char* line); // this is not C++!
class InstrumentReader
{
void load(const char* fileName)
{
for each line in fileName
{
Class theClass = read(line);
Instrument* instrument = new theClass;
}
}
...
};
7/1/2016
CS 631: Object Factory
4
Basic Implementation
// a unique ID for each instrument type
namespace InstrumentType
{
const int
FORWARD = 1,
BOND = 2
};
void InstrumentReader::load(std::ifstream& inFile)
{
char s[256];
while(inFile.getline(s, 256))
{
stringstream line(s);
// read object type
int instrumentType;
line >> instrumentType;
7/1/2016
CS 631: Object Factory
5
Basic Implementation: Reading Instrument
Instrument* pCurrentInstrument;
switch (instrumentType)
{
using namespace InstrumentType;
case FORWARD:
pCurrentInstrument = new ForwardContract;
break;
case BOND:
pCurrentInstrument = new Bond;
break;
default:
... handle error – unknown type ...
}
// read the instrument's contents by invoking a virtual
// function
pCurrentInstrument->read(line.str());
... add the object to container, etc. ...
}
7/1/2016
CS 631: Object Factory
6
Basic Implementation: Drawbacks
• It performs switch based on a type tag, which is
exactly what object-oriented programs try to eliminate.
• One class (single source file) has knowledge about all
Instrument-derived classes.
– It must include all headers of all possible instruments.
• It is hard to extend. Creating another type of
instrument involves:
– add a distinct integral constant to InstrumentType;
– output that constant when saving the instrument;
– add a new label to the switch statement
7/1/2016
CS 631: Object Factory
7
InstrumentFactory Class
class InstrumentFactory
{
public:
// Define a callback function pointer.
// The function will create a concrete instrument pointer.
typedef Instrument* (*CreateInstrumentCallback)();
private:
// Define a map that keeps a unique instrument type
// associated with a callback function pointer.
typedef std::map<int, CreateInstrumentCallback>
CallbackMap;
public:
// It is a Singleton!
static InstrumentFactory& getInstance() {...}
// Instrument registration: true if successful
bool register(int id, CreateInstrumentCallback fn);
// The function that "manufactures" an instrument
Instrument* create(int instrumentId);
private:
CallbackMap callbacks;};
7/1/2016
CS 631: Object Factory
8
Instrument Registration
// In Bond.cpp file:
...
// Registration code in an anonymous namespace to make the
// function invisible from other modules.
namespace
{
// Trivial callback function
Instrument* createBond() {return new Bond;}
const int BOND = 2;
// This will be created as a static variable
const bool registered =
InstrumentFactory::getInstance().register(
BOND, createBond);
}
// In ForwardContract.cpp file, similar registration ...
7/1/2016
CS 631: Object Factory
9
Implementing InstrumentFactory
bool InstrumentFactory::register(int instrumentId,
CreateInstrumentCallback createFn)
{
// Simply add to the map. (The insert method returns a
// pair, with the second element being a success flag.)
return this->callbacks.insert(
CallbackMap::value_type(instrumentId, createFn)).second;
}
// Create an instrument pointer based on id
Instrument* InstrumentFactory::create(int id)
{
CallbackMap::const_iterator i = this->callbacks.find(id);
if (i == this->callbacks.end())
throw std::runtime_error("Unknown Instrument Id");
// invoke the creation function:
return (i->second)();
}
7/1/2016
CS 631: Object Factory
10
InstrumentReader Implementation
// Loading different instruments from a file
void InstrumentReader::load(std::ifstream& inFile)
{
char s[256];
while(inFile.getline(s, 256))
{
stringstream line(s);
// read object type:
int instrumentType;
line >> instrumentType;
Instrument* pCurrentInstrument =
InstrumentFactory::getInstance().create(instrumentType);
... process the instrument ...
}
}
7/1/2016
CS 631: Object Factory
11
Generalization: Object Factory Elements
• Concrete Product (Bond, ForwardContract)
– A factory delivers some product in the form of an object.
• Abstract Product (Instrument)
– All products inherit from a base class.
• Product Type Identifier
– Need to have because of the static C++ type system.
• Product Creator
– The function or functor specialized for creating exactly one
type of object.
7/1/2016
CS 631: Object Factory
12
Generic Object Factory
template
<
class AbstractProduct,
typename IdentifierType,
typename ProductCreator
>
class Factory
{
private:
typedef std::map<IdentifierType, ProductCreator>
AssocMap;
AssocMap associations;
7/1/2016
CS 631: Object Factory
13
Generic Object Factory: Implementation
public:
bool register(const IdentifierType& id,
ProductCreator creator)
{
return this->associations.insert(
AssocMap::value_type(id, creator);
}
AbstractProduct* create(const IdentifierType& id)
{
typename AssocMap::const_iterator i =
this->associations.find(id);
if (i != this->associations.end())
return (i->second)();
throw (...);
}
};
7/1/2016
CS 631: Object Factory
14
Generic Object Factory: Usage
// Loading different instruments from a file
void InstrumentReader::load(std::ifstream& inFile)
{
typedef Instrument* (*CreateInstrumentCallback)();
// Use SingletonHolder to ensure singleton behavior
typedef SingletonHolder<Factory<
Instrument,int,CreateInstrumentCallback> >
InstrumentFactory;
char s[256];
while(inFile.getline(s, 256))
{
stringstream line(s);
int instrumentType;
line >> instrumentType;
Instrument* pCurrentInstrument =
InstrumentFactory::getInstance().create(instrumentType);
... process the instrument ...
}
}
7/1/2016
CS 631: Object Factory
15
Download