//---prototype--------------------------------------------------------
// creational design pattern
// ---intent
// create objects by copying a prototype
// ---benefits------------------------------------------------------
// class of object that is instantiated may vary
// ---refactoring problem
// creating an object by specifying a class explicitly
// ---solution
// create objects indirectly
// also abstract factory, factory method
// ---applicability ------------------------------------------------
// classes to instantiate are specified at run-time
// no duplication of factories/products class hierarchies
// objects have one of a few combinations of state
// install prototypes and clone them
// don't instantiate the class with state manually
// ---structure
// prototype
// | Client |--------------------->|Prototype|
// |--------------------| |---------|
// |Operation() | |Clone() |
// | p=prototype.Clone()| ^
// |
// +--------------+---------------+
// | |
// | ConcretePrototype1 | | ConcretePrototype2 |
// |--------------------| |--------------------|
// |Clone() | |Clone() |
// | return copy of self| | return copy of self|
//
#include <SRC\Patterns\Patterns.mqh>
namespace Prototype
{
//---participants-----------------------------------------------------
class Prototype //interface for cloning itself
{
public:
int id;
virtual Prototype* Clone()=0;
Prototype(int);
};
Prototype::Prototype(int i):id(i) {}
//---participants-----------------------------------------------------
class ConcretePrototype1:public Prototype
//implements an operation for cloning itself
{
public:
ConcretePrototype1(int);
Prototype* Clone();
};
ConcretePrototype1::ConcretePrototype1(int i):Prototype(i) {}
Prototype* ConcretePrototype1::Clone(void)
{
Print("Cloning Concrete Prototype 1 with id: ",id);
return new ConcretePrototype1(id);
}
//---participants-----------------------------------------------------
class ConcretePrototype2:public Prototype
//implements an operation for cloning itself
{
public:
ConcretePrototype2(int);
Prototype* Clone();
};
ConcretePrototype2::ConcretePrototype2(int i):Prototype(i) {}
Prototype* ConcretePrototype2::Clone(void)
{
Print("Cloning Concrete Prototype 2 with id: ",id);
return new ConcretePrototype2(id);
}
//---participants-----------------------------------------------------
class Client:public ClientExample
//creates a new object by asking a prototype to clone itself
{
public:
string Output();
void Run();
};
string Client::Output() {return __FUNCTION__;}
//---collaborations---------------------------------------------------
// client asks a prototype to clone itself
void Client::Run()
{
Prototype* prototype;
Prototype* clone;
prototype=new ConcretePrototype1(1);
clone=prototype.Clone();
delete prototype;
delete clone;
//---
prototype=new ConcretePrototype2(2);
clone=prototype.Clone();
delete prototype;
delete clone;
}
}
//---output-----------------------------------------------------------
// Creational::Prototype::Client::Output
// Cloning Concrete Prototype 1 with id: 1
// Cloning Concrete Prototype 2 with id: 2
//---consequences-----------------------------------------------------
// ---hides the concrete product classes from the client
// reduces the number of names clients know about
// ---lets a client work with application-specific classes without modification
// ---adding and removing products at run-time
// register a prototypical instance with the client
// more flexible than other creational patterns
// ---specifying new objects by varying values
// define new behavior through object composition
// define new kinds of objects by
// instantiating existing classes
// registering the instances as prototypes of client objects
// cloning a prototype is similar to instantiating a class
// ---specifying new objects by varying structure
// build objects from parts and subparts
// as long as the composite circuit implements clone as a deep copy
// circuits with different structures can be prototypes
// ---reduced subclassing
// clone a prototype
// don't ask a factory method to make a new object
// creator hierarchy not needed at all
// ---configuring an application with classes dynamically
// run-time
// object is created automatically when it's loaded
// object with a prototype manager is registered
// objects of newly loaded classes are provided
// weren't linked with the program originally
//---implementation --------------------------------------------------
// ---prototype manager
// client will ask the manager for a prototype before cloning it
// prototype manager
// associative store
// returns the prototype matching a given key
// clients at run-time can change, browse it
// ---clone()
// default copy constructor in c++ does a member-wise copy
// pointers will be shared between the copy and the original
// cloning prototypes with complex structures requires a deep copy
// clone and original must be independent
// save()
// the object into a memory buffer
// load()
// duplicate by reconstructing the object from the buffer
// ---initializing clones
// initialize()
// takes initialization parameters as arguments
// sets the clone's internal state
// beware of deep-copying clone operations
// copies may have to be deleted before reinitialization
// explicitly or in initialize()
//---related patterns-------------------------------------------------
// ---abstract factory
// competes in some ways
// can also be used together
// store a set of prototypes from which to clone and return product objects
// ---composite, decorator
// often can benefit from prototype
#30482LibrariesMetaTrader 5👁 3907 views
Design patterns - Prototype (creational)
D
Author
DMITRII PECHERITSAPublished date
Aug 5, 2020
📚Related Articles
← View other articles →#77531Libraries
CSetupLedger: a per-setup win rate ledger for Expert Advisors
Why I wrote it My scalper trades two setups. A bullish order block and the bearish mirror of it. The Strategy Tester gave me one profit factor for both of them. I spent two weeks t...
Ali AkbarView detail →
#77488Libraries
Position sizing from risk, using the broker's own tick value and volume step
Every lot size calculator that assumes one pip is worth ten dollars is wrong on gold, wrong on indices, wrong on JPY crosses and wrong on any account not denominated in USD which i...
Ralph Ivan SimeonView detail →
#77156Libraries
PropFirm Defense
A prop firm account runs under a second rulebook MetaTrader 5 knows nothing about: a maximum loss measured from a fixed starting balance, a daily limit that resets at an hour the b...
Bruno Nunes Myrrha RibeiroView detail →