Ich verwende ein Framework namens Processing, die im Grunde ein Java-Applet ist. Es hat die Fähigkeit, Schlüsselereignisse zu tun, weil Applet es kann. Sie können auch Ihre eigenen Rückrufe von Arten in den übergeordneten Ordner rollen. Ich mache das jetzt nicht und vielleicht ist das die Lösung. Für jetzt suche ich nach einer mehr POJO Lösung. Also habe ich einige Beispiele geschrieben, um meine Frage zu illustrieren.Beobachten einer Variablen für Änderungen ohne Abfrage
Bitte ignorieren Sie Schlüsselereignisse in der Befehlszeile (Konsole). Sicherlich wäre das eine sehr saubere Lösung, aber es ist nicht in der Befehlszeile möglich und meine eigentliche App ist keine Befehlszeilen-App. In der Tat wäre ein Schlüsselereignis eine gute Lösung für mich, aber ich versuche Ereignisse und Abfragen zu verstehen, die über die Tastatur hinausgehen.
Beide Beispiele spiegeln einen booleschen Wert. Wenn der boolesche Flipflop ausgelöst wird, möchte ich einmal etwas auslösen. Ich könnte den Booleschen Wert in ein Objekt einfügen. Wenn sich das Objekt ändert, könnte ich also auch ein Ereignis auslösen. Ich will einfach nicht unnötig mit einer if() -Anweisung abfragen.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/*
* Example of checking a variable for changes.
* Uses dumb if() and polls continuously.
*/
public class NotAvoidingPolling {
public static void main(String[] args) {
boolean typedA = false;
String input = "";
System.out.println("Type 'a' please.");
while (true) {
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
try {
input = br.readLine();
} catch (IOException ioException) {
System.out.println("IO Error.");
System.exit(1);
}
// contrived state change logic
if (input.equals("a")) {
typedA = true;
} else {
typedA = false;
}
// problem: this is polling.
if (typedA) System.out.println("Typed 'a'.");
}
}
}
Ausführen dieser Ausgänge:
Type 'a' please.
a
Typed 'a'.
In einigen Foren Menschen mit einem Beobachter vorgeschlagen. Und obwohl dies den Ereignishandler von der beobachteten Klasse entkoppelt, habe ich immer noch ein if() für eine forever-Schleife.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Observable;
import java.util.Observer;
/*
* Example of checking a variable for changes.
* This uses an observer to decouple the handler feedback
* out of the main() but still is polling.
*/
public class ObserverStillPolling {
boolean typedA = false;
public static void main(String[] args) {
// this
ObserverStillPolling o = new ObserverStillPolling();
final MyEvent myEvent = new MyEvent(o);
final MyHandler myHandler = new MyHandler();
myEvent.addObserver(myHandler); // subscribe
// watch for event forever
Thread thread = new Thread(myEvent);
thread.start();
System.out.println("Type 'a' please.");
String input = "";
while (true) {
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
try {
input = br.readLine();
} catch (IOException ioException) {
System.out.println("IO Error.");
System.exit(1);
}
// contrived state change logic
// but it's decoupled now because there's no handler here.
if (input.equals("a")) {
o.typedA = true;
}
}
}
}
class MyEvent extends Observable implements Runnable {
// boolean typedA;
ObserverStillPolling o;
public MyEvent(ObserverStillPolling o) {
this.o = o;
}
public void run() {
// watch the main forever
while (true) {
// event fire
if (this.o.typedA) {
setChanged();
// in reality, you'd pass something more useful
notifyObservers("You just typed 'a'.");
// reset
this.o.typedA = false;
}
}
}
}
class MyHandler implements Observer {
public void update(Observable obj, Object arg) {
// handle event
if (arg instanceof String) {
System.out.println("We received:" + (String) arg);
}
}
}
Ausführen dieser Ausgänge:
Type 'a' please.
a
We received:You just typed 'a'.
würde ich in Ordnung sein, wenn der if() wurde ein NOOP auf der CPU. Aber es vergleicht wirklich jeden Durchgang. Ich sehe echte CPU-Last. Das ist so schlecht wie das Polling. Ich kann es vielleicht mit einem Schlaf zurückdrosseln oder die vergangene Zeit seit dem letzten Update vergleichen, aber dies ist nicht ereignisgesteuert. Es ist nur weniger Umfragen. Wie kann ich das klüger machen? Wie kann ich ein POJO für Änderungen ohne Abfrage sehen?
In C# scheint es etwas Interessantes namens Eigenschaften zu geben. Ich bin kein C# Typ, also ist das vielleicht nicht so magisch wie ich denke.
Hinweis: Observable/Observer ist vergleichbar mit der Ereignisbehandlung. Dies ist ein Hybrid-Event-Handler/Beobachter-Muster, das sehr einfach zu verwenden ist. Es kann weiter verbessert werden, so dass "firePropertyChanged" Reflektion verwendet, um das private Feld zu modifizieren. Dann sind alle Setter-Methoden sehr sauber und wartbar, obwohl die Leistung abnehmen könnte. – Pindatjuh