It’s #FrontendFriday – Mediator (Publish Subscribe)

20.05.2022

Hallo #FrontendFriday-Leser/in. Heute zeigen wir euch das nächste Coding Pattern aus der Gruppe der Behavioral Design Pattern (Verhaltensmuster): Mediator (Publish Subscribe).

Was ist der Mediator?

Kurz gesagt: Ein Mediator ist eine Event Channel, der zwischen allen Components steht und die Interaktion zwischen den Components leitet.

 

 

Um das genau zu verstehen, müssen wir erstmal den Unterschied zwischen Observer und dem Publish-Subscribe-Pattern verstehen.

Unterschied Observer und Publish-Subscribe-Pattern

Observer: Ein Subject (Objekt) beinhaltet die gesamte Logik für das Event-Management und die Event-Handler werden hier gespeichert. Das heißt alle anderen Objekte können nur auf dieses eine Subject subscriben => Eine one-to-many Connection.

Publish/Subscribe: Die komplette Kommunikationslogik wird innerhalb eines Event Channels durchgeführt. Dieser Event Channel beinhaltet alle Interfaces und es speichert alle Event-Handler. Jedes Objekt kann auf diesen Event Channel publishen und subscriben => Eine many-to-many Connection.

Der Mediator erweitert das Prinzip des Publish-Subscribe-Pattern. Er wird auf Application-Level genutzt und kümmert sich um das Event-Handling aller Components. Die Vorteile vom Publish-Subscribe-Pattern bleiben bestehen, jedoch verhindert der Mediator komplexe Beziehungen zwischen Components. Es gibt keine strikten Abhängigkeiten zwischen Komponenten.

Mediator Veranschaulichung

Beispiel: Die Database hat seine Daten aktualisiert und will das dem Diagram mitteilen. Hier würde die Database nicht direkt eine Methode vom Diagram Interface aufrufen, sondern er würde ein Event zu dem Mediator publishen. Das Diagram hört auf dieses Event und will somit einen neuen Shape zeichnen. Dafür published das Diagram ein neuen Event an den Mediator. Das Shape hört auf dieses Event und führt seine Logik durch. Kurz gesagt: Alles geht durch den Mediator.

Code-Example

Hier ein Code-Example, wie die Datenaktualisierung von Beispiel oben aussehen könnte:

class Mediator{
  constructor() {

    // Collection of handlers
    let handlers = {}; 

    // Method to publish the change
    this.publish = function(name, args) {
      handlers[name].map(handler => handler(args));
    };

    // Method for subscription on event
    this.subscribe = function(name, handler) {
      if (typeof handlers[name] === 'undefined') {
        handlers[name] = [];
      }
      handlers[name].push(handler);
    }

    // Method to unsubscribe from event
    this.unsubscribe = function(name, handlers) {
      handlers[name] = handlers[name].filter(storedHandler => storedHandler !== handler);
    };
  }
}

class Shape {
  constructor(name, channel) {
    function init() {
      /** ... some load logic ... **/
      channel.publish('loadedShape', this);
    }
    
    this.name = name;
    init();
  };
}

class Diagram {
  constructor(channel) {
    function init() {
      channel.subscribe('newShape', shape => {
        new Shape(shape, channel);
      });
      channel.subscribe('loadedShape', shapeObj => {
        console.log(shapeObj);
      })
    }
    
    init();
  }
}

class Database {
  constructor(channel) {
    function init() {
      this.getUpdates();
    }
    
    this.getUpdates = function() {
      let addedEntities = ['rect1', 'rect2', 'rect3'];
      addedEntities.map(ent => channel.publish('newShape', ent));
    }
    
    init();
  }
}

(function() {
  let mediator = new Mediator();
  let diagram = new Diagram(mediator);
  let database = new Database(mediator);
})()

Sobald die Funktion getUpdates() aus der Database aufgerufen wird, werden die Daten in den Channel „newShape“ gepublished. Das Diagram hört auf diesen Channel „newShape“ und initialisiert dort ein neues Shape (vereinfacht). Im Shape wird dann die dazugehörige Logik aufgerufen. Sobald das fertig ist, wird der Channel „loadedShape“ mit den dazugehörigen Daten gepublished. Diagram hört auf „loadedShape“ und führt in unserem Beispiel ein console.log aus.

Relevanz in JavaScript

Mit steigender Anzahl an Components, steigt auch die Komplexität. Hierbei ist der Einsatz von einem Mediator sinnvoll, da es den Code vereinfacht und die Lesbarkeit erhöht.


Quelle: https://soshace.com/programming-patterns-publishersubscriber-mediator/

Zurück zur Übersicht

Kommentar verfassen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

*Pflichtfelder

*