//---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