我正在使用一个名为Processing的框架,它基本上是一个Java小程序。它有能力做关键事件,因为Applet可以。您也可以将自己的回调放入父级。我现在没有这样做,也许这就是解决方案。现在,我正在寻找更多POJO解决方案。所以我写了一些例子来说明我的问题。在没有轮询的情况下观察变量的变化
请忽略在命令行(控制台)上使用键盘事件。当然,这将是一个非常干净的解决方案,但它不可能在命令行上,我的实际应用程序不是命令行应用程序。事实上,一个关键事件对我来说是一个很好的解决方案,但我试图理解事件和轮询,而不仅仅是键盘特定的问题。
这两个例子翻转布尔值。布尔翻转时,我想发射一次。我可以将布尔值封装在一个对象中,所以如果对象发生变化,我也可以触发一个事件。我只是不想用if()语句进行不必要的轮询。
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'.");
}
}
}
运行此输出:
Type 'a' please.
a
Typed 'a'.
在一些论坛上的人使用一个观察员建议。尽管这样可以将事件处理程序从正在被观察的类中分离出来,但我仍然有一个if()永久循环。
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);
}
}
}
运行此输出:
Type 'a' please.
a
We received:You just typed 'a'.
我很确定,如果如果()是一个在CPU上NOOP。但它真的比较每一个传球。我看到真正的CPU负载。这和投票一样糟糕。我可以通过睡眠来调节它,或者比较自上次更新以来的经过时间,但这不是事件驱动的。这只是较少的投票。那么我怎么能做到这一点更聪明?如何在没有投票的情况下观看POJO的更改?
在C#中似乎有一些有趣的属性。我不是C#的人,所以也许这不像我想象的那样神奇。
private void SendPropertyChanging(string property)
{
if (this.PropertyChanging != null) {
this.PropertyChanging(this, new PropertyChangingEventArgs(property));
}
}
注意:Observable/Observer很像事件处理。这是一个混合事件处理程序/观察者模式,它非常易于使用。它可以进一步改进,使“firePropertyChanged”使用反射来修改私人领域。然后所有的setter方法都非常干净和可维护,但性能可能会下降。 – Pindatjuh 2010-05-12 22:28:35