2016-05-16 8 views
1

Mit knockout.js computed observables ist es möglich, eine JavaScript-Observable zu definieren, die von anderen Observablen abhängt, wobei ein funktionaler Ausdruck, z.Java-Äquivalent für Knockout.js berechnete Observablen?

var computedObservable = ko.computed(function(){ 
    return firtName() + lastName(); 
}); 

Wenn eine der referenzierten Observablen (z.B. vorName) ändert, aktualisiert die berechnete beobachtbar ist automatisch. Die referenzierten Observablen sind durch den angegebenen Funktionsausdruck definiert und müssen nicht explizit angegeben werden.

Wie kann ich etwas Ähnliches in Java implementieren?

(Nun, es gibt JavaFx Bindings, aber sie bedürfen der ausdrücklichen Registrierung der referenzierten Eigenschaften/Observablen.)

I unterscheiden zwei Fälle:

a) Der Ausdruck Lambda wird analysiert, mit Java zu automatisch herausfinden, welche referenzierten Observablen berücksichtigt werden müssen. (Die genannten Observablen könnten weitere Observablen in einer Abhängigkeitskette verweisen.) Expected Beispielcode:

ComputedObservable<String> computedObservable = new ComputedObservable<>(() -> { 
    return firstName.get() + lastName.get(); 
}); 

b) ich manuell verwiesen beobachtbaren jeder registrieren, um sie zu beobachten. Ich möchte diesen Fall vermeiden. Mit anderen Worten ich nicht will Code hat wie

ComputedObservable<String> computedObservable = new CoputedObservable<>(); 
computedObservable.registerReference(firstName); 
computedObservable.registerReference(lastName); 
computedObservable.setExpresion(() -> { 
     return firstName.get() + lastName.get(); 
}); 

oder (mit JavaFx Bindings)

DoubleBinding db = new DoubleBinding() { 
     { 
      super.bind(a, b, c, d); 
     } 

     @Override 
     protected double computeValue() { 
      return (a.get() * b.get()) + (c.get() * d.get()); 
     } 
}; 

Ist Fall a) möglich, überhaupt und wenn ja, gibt es eine vorhandene Java-Implementierung/Bibliothek dafür?

Edit: Es gibt eine andere Strategie:

c) Verwenden spezialisierte Operatoren den funktionellen Ausdruck zu definieren. Diese Operatoren registrieren implizit die referenzierten Observablen. Es ist also kein zusätzlicher manueller Registrierungsschritt erforderlich. (Der Funktionsausdruck wird auf die verfügbaren Operatoren beschränkt, und die erweiterte Funktionalität erfordert möglicherweise die Implementierung neuer helfender Operatoren.

)
StringBinding fullName = firstName.concat(secondName); 
DoubleBinding result = a.multiply(b).add(c.multiply(d)); 

Verwandte Fragen:

+2

Denken Sie daran, nur weil etwas in Javascript Sinn macht, bedeutet nicht, dass Sie versuchen sollten, es nach Java zu bringen. – Kayaman

+0

Sind Ihre Zweifel bereits in den Widersprüchen enthalten, die ich in meiner Antwort mit der "Registrierungsstrategie" erwähnt habe? Oder gibt es weitere Punkte, die den Ansatz von knockout.j für Java unbrauchbar machen würden? – Stefan

+0

Nun, mein Hauptpunkt war, dass, wo Javascript nativ so etwas unterstützt, es in Java keinen ähnlichen Mechanismus gibt. Das bedeutet, dass Sie kämpfen werden, um Java in Javascript schreiben zu können. Das ist oft ein Zeichen, dass Sie etwas falsch machen. So speichern Sie nicht relationale Daten in einem RDBMS. – Kayaman

Antwort

1

Auch wenn Sie JavaFX bi ausdrücklich ausgeschlossen Ich denke, sie sind am ehesten ohne komplizierte Reflexion (oder sogar Bytecode) Hacking.

Ihr Snippet ist ein Modell Anwendungsfall für Bindings::concat:

ObservableValue<String> firstName = ...; 
ObservableValue<String> lastName = ...; 
StringExpression name = Bindings.concat(firstName, " ", lastName); 

Bindings definiert jede Menge nützliche atomics aber es ist denkbar, dass Sie erweiterte Bedürfnisse wie a*b + c*d haben. Hilfsmethoden zur Rettung!

NumberBinding result = MyBindings.multiplyAndAdd(a, b, c, d); 

mit

public NumberBinding multiplyAndAdd(
     ObservableNumberValue a, ObservableNumberValue b, 
     ObservableNumberValue c, ObservableNumberValue d) { 
    return Bindings.add(Bindings.multiply(a, b), Bindings.multiply(c, d)); 
} 

Sollte das nicht Ihre Anforderungen zu erfüllen?

PS: Ihr Link für JavaFX Bindings verweist auf die Dokumentation der Version 2. Sie sollten bei der Recherche nach JavaFX unbedingt nach "JavaFX 8" suchen.

+0

Die JavaFx-Bindungen in Kombination mit ihren spezialisierten Operatoren scheinen also die besten zu sein, die ich bekommen kann. Die spezialisierten Operatoren registrieren implizit die referenzierten Observablen und definieren den Funktionsausdruck. DoubleBinding-Ergebnis = a.multiply (b) .add (c.multiply (d)); (Ich habe den JavaFx-Link auf die Referenzversion 8 der Dokumentation aktualisiert.) – Stefan

0

Vielleicht wäre folgende Strategie auch funktionieren, eine statische Registrierung mit für alle Observablen:

  • eine erste Bewertung der gegebenen Lambda-Do. Während der Lambda-Ausdruck ausgeführt wird, haben die Methoden der referenzierten Observablen einen Seiteneffekt: Sie teilen der Registry mit, dass sie aufgerufen wurden.
  • Rufen Sie die Liste der referenzierten Observablen aus der Registrierung ab.
  • Setzen Sie die Registrierung zurück.
  • Hängen Sie Listener an die referenzierten Observablen an, um den aktuellen Aktualisierungszyklus zu definieren.
  • Beim erneuten Auswerten des Ausdrucks den Aktualisierungszyklus erneut erstellen.

Ein ähnlicher Arbeitsablauf für Knockout berechnet Observablen wird hier näher erläutert:

http://knockoutjs.com/documentation/computed-dependency-tracking.html

Cons für diese Strategie sein könnte (gibt es weitere solche?):

  • Ein Leistung Verlust aufgrund der Registrierung Overhead und Update-Zyklus aktualisieren.
  • Könnte nicht gut mit Multi-Threading (JavaScript wird in der Regel in einem einzigen Thread)
  • Die einzige Registry hat für (bekannt durch) alle Observablen zur Verfügung steht. (In JavaScript hatte ich einmal das Problem, dass für ein Test-Framework eine zweite Instanz von Knockout verwendet wurde. Die Testcode-Observablen spielten nicht zusammen mit den Observablen im getesteten Code, bis ich einen Verweis auf die Knockout-Instanz des Testcodes eingab .)

Pros:

  • die Definition von berechneten Observablen intuitiver und leichter Wicht wäre: Keine Notwendigkeit, spezialisierte Betreiber zu verwenden/lernen, da alle Informationen, die ist erforderlich bereits in der funktionalen expre enthalten ssion.