2017-07-26 5 views
0

Lassen Sie mich damit beginnen, dass dies eher eine Frage der Neugier ist, denn, wie Sie sehen werden, war ich in der Lage, die gewünschte Funktionalität zu erreichen.
Angesichts der Tatsache, dass Javascript eine super flexible Sprache ist, würde Ich mag, was andere Entwickler sehen könnte über dieses Problem denken:Javascript - dekoriere eine Klasseninstanz, ohne explizit alle Funktionen weiterzugeben

ich eine Instanz einer Klasse, die von einem Lieferanten Funktion zurückgegeben wird:

const connection = vendorDatabaseLib.createConnection(); 

Jetzt möchte ich einen Dekorator erstellen, der der Verbindungsklasse Funktionalität hinzufügt, z. B. Reconnection-Logik.
Lässt es PersistentConnection anrufen. Abgesehen von meinen zusätzlichen benutzerdefinierten Funktionen möchte ich eine Instanz von PersistentConnection, um alle Funktionsaufrufe an die ursprüngliche Connection Instanz weiterzuleiten. Und überschreiben Sie in einigen Funktionen das Verhalten.
Ich könnte natürlich alle Funktionen Connection explizit implementieren und sie an das innere Objekt weiterleiten, aber es könnte viele dieser Funktionen geben, so dass ich diese Idee schnell verworfen habe.

So sind hier meine Ideen, wie diese zu erreichen:

  1. Affen Patchen, statt Dekorateur kann ich eine PersistentConnection Klasse erstellen, die von dem Anbieter erbt Connection und dann den Verkäufer vendorDatabaseLib.createConnection Funktion Patch PersistentConnection zurückzukehren mit all meinen gewünschten zusätzlichen Funktionen. Verlockend, aber schlecht.
  2. einen Dekorateur erstellen, die iteriert über die Connection Funktionen und wie vorwärts dynamisch, etwas schafft:

class PersistentConnection{ 
 
    constructor(connection){ 
 
    this._connection = connection; 
 
     
 
    // Iterate through all functions 
 
    for (prop in this._connection){ 
 
     if(typeof(this._connection[prop]) === 'function'){ 
 
      // Create functions dynamically for each forward 
 
      this[prop] = (...args) => { 
 
      this._connection[prop](...args); 
 
      } 
 
     } 
 
    } 
 
    } 
 

 
    // This is the added logic 
 
    reconnect(){ 
 
    // Custom logic 
 
    } 
 
}

  1. Stellen Sie die ConnectionInstanz ein Prototyp der PersistentConnection 's Instanz sein:

function persistenChannel(channel){ 
 
    const persistentChannel = {}; 
 
    Object.setPrototypeOf(persistentChannel, channel); 
 
    persistentChannel.reconnect =() => { 
 
    // custom logic 
 
    } 
 
}

Dies ist der „Automatik“ Weg, ich .. denken konnte Aber es gerade nach unten rechts hässlich, und die benutzerdefinierten Funktionen müssen jedes Mal eine Instanz erstellt wird, erklärt werden.

Ich fühle mich immer noch, wie ich etwas, so etwas wie Rubys magische method_missing (oder Pythons __getattr__) Funktion bin fehlt, die kurz vor einer method is missing Ausnahme ausgelöst genannt wird, und lässt Sie „Sicherheitsnetz“ Logik definieren (wie alle Anrufe zu delegieren zu die innere _connection Objekt.
gibt es einen besseren Weg, um diese Funktionalität zu erreichen? vielen Dank [=

Antwort

1

Lets aus beginnen, was wir haben. In jedem Fall wird der größte Teil des functionaliy durch Anbieter Objekt durchgeführt werden. wir Ich weiß nicht, wie die Details realisiert werden, so dass wir uns nicht darauf verlassen können, dass dieses Objekt keinen Zustand hat. Das heißt, dass wir auf jeden Fall neu brauchen Verbindungsobjekt für die neue persistentConnection.Dies kann mit proxy object

erreicht werden Lets versuchen, dies zu tun:

function Connection() { 
    this.connect =() => console.log('connected by Connection class'); 
    this.disconnect =() => console.log('disconnected by Connection class'); 
} 


function persistantConnectionFactory() { 
    function PersistentConnection() { 
     this.checkConnection =() => console.log('no connection'); 
    } 
    const instance = new PersistentConnection(); 
    const proxy = new Proxy(instance, { 
     get: function (target, name) { 
      if (!(name in target)) { 
       console.log('adding new prototype') 
       Object.setPrototypeOf(instance, new Connection()) 
      } 

      return target[name]; 
     } 
    }); 

    return proxy; 
} 

var c = persistantConnectionFactory(); 
c.checkConnection(); 
c.connect(); 

Ist diese Lösung gut? Ich denke nicht. Ohne gute Gründe führt dies zu einer Komplexität ohne Wert. Prototyp sollte genug sein.

+0

Schön! Proxy ist das fehlende Link, nach dem ich gesucht habe! –

+1

@PavelTarno Fühlen Sie sich frei, als Antwort zu markieren, wenn es eine Antwort ist :) – Vitalii

Verwandte Themen