title: JavaScript | Angular | Mediator Pattern: Tactics for Obviating Circular Dependencies In AngularJS
body: <h2>Ways to Implement Dependency Inversion Principle in AngularJS</h2>
  
  <h3>Case Study: The Mediator Pattern</h3>
  
  <p>Normally, implementing a Mediator/Director entails both <em>Director</em> <strong>and</strong> <em>Colleague(s)</em> having a reference to each other. <strong>Not difficult when Director is responsible for <em>Module-Lifecycle Management (MLM)</em></strong>:</p>
  
  <p>Director creates Colleagues while passing itself in during construction:</p>
  
  <pre><code>var Director = function Director($$) {
      ...
  
      function init(...) {
          _moduleA = new ModuleA(this);
          _moduleB = new ModuleX(this);
          _moduleX = new ModuleX(this);
      }
  
      function moduleChanged(ref) {
          if (ref === _moduleXYZ) _moduleC.run(ref.datum);
      }
  
      return this;
  };
  </code></pre>
  
  <h3>The Tricky Part: Angular</h3>
  
  <p>AngularJS automatically <em>takes on the burden of MLM</em>, so its tough to use the approach above. We <em>could</em> modify our Director.init method slightly:</p>
  
  <pre><code>_moduleX = $dependency;
  ...
  _moduleX.init(this);
  </code></pre>
  
  <p>But [my] Colleagues need a reference to Director <strong>at construction-time</strong>.</p>
  
  <h3>Question and Explanation</h3>
  
  <p>While my Director <em>is</em> implemented as EDM (Event-Driven Mediation) to run away from needing DIP, I now need Colleagues to reference Director:</p>
  
  <pre><code>var Colleague = function Colleague(director) {
      var thus = this;
      ...
  
      director.publish(director.CHANNELS.SOME_CHANNEL_NAME, data);
  
      ...
      return this;
  };
  </code></pre>
  
  <p>This is because Director <em>must</em> now provide Module Authorization (MA): </p>
  
  <pre><code>var Director = function Director($$) {
      ...
  
      function subscribe(channel, handler) {
          var args = Array.prototype.slice.call(arguments, 0);
          $rootScope.$on.apply($rootScope, args);
          return this;
      }
  
      function publish(channel) {
          var args = Array.prototype.slice.call(arguments, 0);
          if (channel in this.CHANNELS) $rootScope.$broadcast.apply($rootScope, args);
          return this;
      }
  
      return this;
  };
  </code></pre>
  
  <p><strong>That said, there's virtually NO-DIFFERENCE -- as far as DIP/DI is concerned -- between this approach and the more <em>Classical</em>, object-reference driven approach first mentioned</strong>.</p>
  
  <p>So my question is, what are different ways that I can <em>elegantly</em> impose DIP and MLM in Angular without running into problems with the framework?</p>
  
  <h3>Concerns &amp; Potential Workarounds</h3>
  
  <ul>
  <li><code>_colleague.init(this);</code>: BAD</li>
  <li><code>_colleague = Colleague.call($dependency, this)</code>: Healthy for Singletons???</li>
  <li>Split state-driven mediation and apply Director Interface to each Colleague</li>
  <li>Mediator Abstract Class [SEE below]</li>
  </ul>
  
  <p><strong>Apply Director Interface to each Colleague</strong></p>
  
  <p>Import (DI) a <em>Mediator</em> class into each Colleague:</p>
  
  <pre><code>var Mediator = function Mediator($rootScope) {
      ...
  
      function subscribe(channel, handler) {
          var args = Array.prototype.slice.call(arguments, 0);
          $rootScope.$on.apply($rootScope, args);
          return this;
      }
  
      function publish(channel) {
          var args = Array.prototype.slice.call(arguments, 0);
          if (channel in this.CHANNELS.SOME_CHANNEL_NAME) $rootScope.$broadcast.apply($rootScope, args);
          return this;
      }
  
      return this;
  };
  angular.factory('Mediator', () =&gt; Mediator);
  
  
  var Colleague = function Colleague(Mediator) {
      var thus = this;
      ...
  
      this.publish(this.CHANNELS.SOME_CHANNEL_NAME, data);
  
      // export precepts
      Mediator.apply(this);
      this.init = init;
      ...
  
      return this;
  };
  </code></pre>
  
  <p>But this <em>could</em> deprive Director of opportunities to mediate based upon high-level application-state, since it won't be a Singleton. E.G:</p>
  
  <pre><code>if (this.state.patientInfoStepComplete) _module.run(ref.datum);
  </code></pre>
  
  <p><strong>Abstract Mediator Class</strong></p>
  
  <p>As in GoF, the <em>Participants</em> include a <strong>Mediator</strong> and a <strong>ConcreteMediator</strong>.</p>
  
  <hr>
  
  <ul>
  <li><p><strong>Mediator</strong>:</p>
  
  <ul>
  <li><em>Defines an Interface for communication with Colleague objects</em></li>
  </ul></li>
  <li><p><strong>ConcreteMediator</strong>:</p>
  
  <ul>
  <li><em>Implements cooperative behavior by coordinating Colleague objects</em></li>
  <li><em>knows and maintains its colleagues</em></li>
  </ul></li>
  </ul>
  
  <hr>
  
  <p>To follow a little closer to DIP, can we take "<code>this.CHANNELS</code>" and encapsulate it in <em>Mediator</em>, but <em>ConcreteMediator</em> would still need a reference to it and Colleague would need a reference to whatever is providing <strong>both</strong> <code>.CHANNELS</code> and <code>.publish(...)</code>.</p>
  
  <p>You may wonder why I need a "Concrete Mediator" when I'm already implementing something of an "Abstract Mediator" through the use of <code>.CHANNELS</code> which can provide <em>Request-Routing</em> anyway since its keys are used by Colleagues to abstract a <em>Channel-Name</em> value. The reason is that, while <code>.CHANNELS</code> <em>can</em> route one request to another, it can only do that -- <em>one single request</em> -- while <code>.publish(...)</code> can provide <em>one-to-many</em> handling <strong>AND</strong> work as middleware in other ways as well (e.g: MA).</p>
  
  <pre><code>var _actions = {
      'SOME_CHANNEL_NAME': (e, a, b, c) =&gt; {
          $rootScope.emit('a', a);
          $rootScope.emit('b', b);
          $rootScope.emitemit('c', c);
      },
  };
  
  function publish() {
      ...
      if (channel in this.CHANNELS) _actions[channel].apply(_actions, args);
      ...
  }
  </code></pre>
  
  <p>Any ideas or patterns you've used or can think of?</p>
  
  <p>Any cool, non-standard tricks for registering/accessing dependencies in Angular?</p>
  
  <p>Any way in Angular to configure another dependency to be injected to Services at run-time?</p>
  
  <p>Call <code>angular.constant('contreteMediator', this);</code> at run-time inside of Director?</p>
  
  <p>Middleware for the Provider-Construction process?</p>
  
  <p><code>#PreThanks</code></p>