//+------------------------------------------------------------------+ //| Bridge.mqh | //| 2019-2020, dmitri pecheritsa | //| 792112@gmail.com | //+------------------------------------------------------------------+ //| bridge > structural design pattern | //+------------------------------------------------------------------+ // design patterns: elements of reusable object-oriented software // gof > erich gamma, richard helm, ralph johnson, john vlissides // published in 1994 //+------------------------------------------------------------------+ //| intent | //+------------------------------------------------------------------+ // abstraction and implementation > decoupled, vary independently //+------------------------------------------------------------------+ //| benefits | //+------------------------------------------------------------------+ // variable aspect > implementation of an object // refactoring problems // dependence on hardware and software platform // dependence on object representations/implementations // tight coupling // extending functionality by subclassing // refactoring solutions // limit platform dependencies // also > abstract factory, bridge // hide the dependence from clients to keep changes from cascading // also > abstract factory, bridge, memento, proxy // decouple with abstract coupling and layering // also // abstract factory, bridge, chain of responsibility, // command, facade, mediator, observer // composition/delegation // more flexible than inheritance for combining behavior // also // bridge, chain of responsibility, composite, decorator, // observer, strategy //+------------------------------------------------------------------+ //| applicability | //+------------------------------------------------------------------+ // abstraction/implementation // not bound > switch implementation at run-time // extensible by subclassing > combine/extend independently // implementation of an abstraction // change has no impact on clients (no recompilation) // can be hidden from clients in c++ // proliferation of classes > split object into two parts // implementation can be shared among multiple objects (reference counting) //+------------------------------------------------------------------+ //| structure | //+------------------------------------------------------------------+ // //|Client| // | // +-->| Abstraction |----------------->| Implementor | // |----------------| |--------------| // |Operation() | |OperationImp()| // | imp.Operation()| ^ // ^ | // | +----------+----------+ // | | | // |RefinedAbstraction| |ConcreteImplementorA| |ConcreteImplementorB| // |--------------------| |--------------------| // |OperationImp() | |OperationImp() | // #include <SRCPatternsPatternOrganizer.mqh> namespace Bridge { //+------------------------------------------------------------------+ //| participants | //+------------------------------------------------------------------+ interface Implementor // defines the interface for implementation classes // implementor interface provides only primitive operations // abstraction defines higher-level operations based on these primitives { void OperationImp(void); }; //+------------------------------------------------------------------+ //| participants | //+------------------------------------------------------------------+ class Abstraction // defines the abstraction's interface // maintains a reference to an object of type implementor { public: virtual void Operation(void); Abstraction(Implementor*); Abstraction(void); ~Abstraction(void); protected: Implementor* implementor; }; void Abstraction::Abstraction(void) {} //+------------------------------------------------------------------+ //| participants > abstraction | //+------------------------------------------------------------------+ void Abstraction::Abstraction(Implementor*i):implementor(i) { Print("abstracton created with implementor ",i); Print("implementor ",i," saved by abstraction"); } //+------------------------------------------------------------------+ //| participants > abstraction | //+------------------------------------------------------------------+ void Abstraction::~Abstraction(void) { delete implementor; } //+------------------------------------------------------------------+ //| participants > abstraction | //+------------------------------------------------------------------+ void Abstraction::Operation(void) { Print("abstraction is requesting in own operation its implementor ", implementor," to run its operation in turn"); implementor.OperationImp(); } //+------------------------------------------------------------------+ //| participants | //+------------------------------------------------------------------+ class RefinedAbstraction:public Abstraction // extends the interface defined by abstraction { public: RefinedAbstraction(Implementor*); void Operation(void); }; //+------------------------------------------------------------------+ //| participants > refined abstraction | //+------------------------------------------------------------------+ void RefinedAbstraction::RefinedAbstraction(Implementor*i):Abstraction(i) { Print("refined abstraction created, received implementor ",i, " via the abstracton constructor"); } //+------------------------------------------------------------------+ //| participants > refined abstraction | //+------------------------------------------------------------------+ void RefinedAbstraction::Operation(void) { Print("refined abstraction operation is running"); Print("refined abstraction ",&this," is requesting its parent's abstraction operation"); Abstraction::Operation(); //... } //+------------------------------------------------------------------+ //| participants | //+------------------------------------------------------------------+ // concrete implementor // implements the implementor interface // defines its concrete implementation //+------------------------------------------------------------------+ //| participants > concrete implementor | //+------------------------------------------------------------------+ class ConcreteImplementorA:public Implementor { public: void OperationImp(void); }; void ConcreteImplementorA::OperationImp(void) { Print("concrete implementor a ",&this," is running operation"); } //+------------------------------------------------------------------+ //| participants > concrete implementor | //+------------------------------------------------------------------+ class ConcreteImplementorB:public Implementor { public: void OperationImp(void); }; void ConcreteImplementorB::OperationImp(void) { Print("concrete implementor b ",&this," is running operation"); } //+------------------------------------------------------------------+ //| participants | //+------------------------------------------------------------------+ class Client:public ClientExample { public: string Output(void); void Run(void); }; string Client::Output(void) {return __FUNCTION__;} //+------------------------------------------------------------------+ //| collaborations | //+------------------------------------------------------------------+ void Client::Run(void) // abstraction forwards client requests to its implementor object { Abstraction* abstraction; //--- Print("creating refined abstraction with concrete implementor a"); abstraction=new RefinedAbstraction(new ConcreteImplementorA); Print("requesting abstraction operation"); abstraction.Operation(); delete abstraction; //--- Print("creating refined abstraction with concrete implementor b"); abstraction=new RefinedAbstraction(new ConcreteImplementorB); Print("requesting abstraction operation"); abstraction.Operation(); delete abstraction; } } //+------------------------------------------------------------------+ //| output | //+------------------------------------------------------------------+ // Structural::Bridge::Client::Output // creating refined abstraction with concrete implementor a // abstracton created with implementor 34603008 // implementor 34603008 saved by abstraction // refined abstraction created, received implementor 34603008 via the abstracton constructor // requesting abstraction operation // refined abstraction operation is running // refined abstraction 33554432 is requesting its parent's abstraction operation // abstraction is requesting in own operation its implementor 34603008 to run its operation in turn // concrete implementor a 34603008 is running operation // creating refined abstraction with concrete implementor b // abstracton created with implementor 36700160 // implementor 36700160 saved by abstraction // refined abstraction created, received implementor 36700160 via the abstracton constructor // requesting abstraction operation // refined abstraction operation is running // refined abstraction 35651584 is requesting its parent's abstraction operation // abstraction is requesting in own operation its implementor 36700160 to run its operation in turn // concrete implementor b 36700160 is running operation //+------------------------------------------------------------------+ //| consequences | //+------------------------------------------------------------------+ // decoupling interface and implementation // can be configured at run-time // no compile-time dependencies/recompilation // encourages layering > better-structured system // high-level part of a system > knows abstraction and implementor // improved extensibility > abstraction and implementor are independent // hiding implementation details from clients //+------------------------------------------------------------------+ //| implementation | //+------------------------------------------------------------------+ // only one implementor // creating the right implementor object // if abstraction knows all concrete implementors // instantiate one of them in its constructor // decide between them based on parameters passed to its constructor // default implementation // choose initially // change later according to usage // delegate the decision to another object (factory) altogether // sharing implementors > handle/body idiom // multiple inheritance // publicly from abstraction // privately from a concrete implementor // binds an implementation permanently to its interface //+------------------------------------------------------------------+ //| related patterns | //+------------------------------------------------------------------+ // abstract factory > create and configure a particular bridge // adapter // geared toward making unrelated classes work together // applied to systems after they're designed // bridge > used up-front in a design //+------------------------------------------------------------------+