//+------------------------------------------------------------------+ //| Proxy.mqh | //| 2019-2020, dimitri pecheritsa | //| 792112@gmail.com | //+------------------------------------------------------------------+ //| proxy — structural design pattern | //+------------------------------------------------------------------+ // design patterns: elements of reusable object-oriented software // gof > erich gamma, richard helm, ralph johnson, john vlissides // published — 1994 //+------------------------------------------------------------------+ //| intent | //+------------------------------------------------------------------+ // provide a surrogate or placeholder for another object // to control access to it //+------------------------------------------------------------------+ //| benefits | //+------------------------------------------------------------------+ // variable aspects > how an object is accessed, its location // code refactoring // problem > dependence on object representations/implementations // solution > hide the dependence from clients — // keep changes from cascading // abstract factory, bridge, memento, proxy //+------------------------------------------------------------------+ //| applicability | //+------------------------------------------------------------------+ // there is a need for a more versatile or sophisticated reference // to an object than a simple pointer // a remote proxy provides a local representative for an object // in a different address space // a virtual proxy creates expensive objects on demand // a protection proxy controls access to the original object // protection proxies are useful when objects should have // different access rights // a smart reference is a replacement for a bare pointer that // performs additional actions when an object is accessed // counting the number of references to the real object so // that it can be freed automatically when there are no more // references // loading a persistent object into memory when it's first // referenced // checking that the real object is locked before it's // accessed to ensure that no other object can change it //+------------------------------------------------------------------+ //| structure | //+------------------------------------------------------------------+ // // |Client|-------------------------->| Subject | // |---------| // |Request()| // |... | // ^ // | // +------------------------------------+------------... // | real_subject | // |RealSubject|<-----------------| Proxy | // |-----------| |----------------------| // |Request() | |Request() | // |... | | ... | // | realSubject.Request()| // | ... | // |... | // //+------------------------------------------------------------------+ //| possible proxy structure at run-time | //+------------------------------------------------------------------+ // // |aClient | // |----------| |aProxy | // |Subject *-|--------->|--------------| |aRealSubject| // |realSubject *-|---------->|------------| // | | // #include <SRCPatternsPatternOrganizer.mqh> namespace Proxy { //+------------------------------------------------------------------+ //| participants > subject | //+------------------------------------------------------------------+ class Subject // defines the common interface for real subject and proxy // so that a proxy can be used anywhere a real subject is expected { public: virtual void Request(void)=0; }; //+------------------------------------------------------------------+ //| participants > real subject | //+------------------------------------------------------------------+ class RealSubject:public Subject // defines the real object that the proxy represents. { public: void Request(void); }; //+------------------------------------------------------------------+ //| participants > real subject > request | //+------------------------------------------------------------------+ void RealSubject::Request(void) { Print("real subject"); } //+------------------------------------------------------------------+ //| participants > proxy | //+------------------------------------------------------------------+ class Proxy:public Subject // maintains a reference that lets the proxy access the real subject // proxy may refer to a subject if the real subject and subject // interfaces are the same // provides an interface identical to subject's so that a proxy // can by substituted for the real subject // controls access to the real subject and may be responsible for // creating and deleting it // remote proxies are responsible for encoding a request and its // arguments and for sending the encoded request to the real // subject in a different address space // virtual proxies may cache additional information about the real // subject so that they can postpone accessing it // protection proxies check that the caller has the access // permissions required to perform a request { protected: RealSubject* real_subject; public: ~Proxy(void); void Request(void); }; //+------------------------------------------------------------------+ //| participants > proxy > destructor | //+------------------------------------------------------------------+ Proxy::~Proxy(void) { delete real_subject; } //+------------------------------------------------------------------+ //| participants > proxy > request | //+------------------------------------------------------------------+ void Proxy::Request(void) { if(!CheckPointer(real_subject)) { real_subject=new RealSubject; } real_subject.Request(); } //+------------------------------------------------------------------+ //| participants > client | //+------------------------------------------------------------------+ class Client:public ClientExample { public: string Output(void); void Run(void); }; string Client::Output(void) { return __FUNCTION__; } //+------------------------------------------------------------------+ //| collaborations | //+------------------------------------------------------------------+ void Client::Run(void) // proxy forwards requests to realsubject when appropriate, // depending on the kind of proxy { Subject* subject=new Proxy; subject.Request(); delete subject; } } //+------------------------------------------------------------------+ //| output | //+------------------------------------------------------------------+ // Proxy::Client::Output // real subject //+------------------------------------------------------------------+ //| consequences | //+------------------------------------------------------------------+ // introduces a level of indirection when accessing an object // a remote proxy can hide the fact that an object resides in a // different address space // a virtual proxy can perform optimizations such as creating an // object on demand // both protection proxies and smart references allow additional // housekeeping tasks when an object is accessed // optimization — copy-on-write // copy the object only if it's modified // the subject must be reference counted // can reduce the cost of copying heavyweight subjects significantly //+------------------------------------------------------------------+ //| implementation | //+------------------------------------------------------------------+ // overloading the member access operator — in c++ // proxy doesn't always have to know the type of real subject // proxy can deal with all realsubject classes uniformly // unless it is going to instantiate real subjects // some proxies have to refer to their subject whether it's // on disk or in memory with address space-independent // object identifiers //+------------------------------------------------------------------+ //| related patterns | //+------------------------------------------------------------------+ // adapter // provides a different interface to the object it adapts // proxy — same // decorator // adds one or more responsibilities to an object // proxy — controls access to an object //+------------------------------------------------------------------+