Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/365.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 观察者设计——如何访问method.invoke范围?_Java_Events_Actionscript_Observer Pattern - Fatal编程技术网

Java 观察者设计——如何访问method.invoke范围?

Java 观察者设计——如何访问method.invoke范围?,java,events,actionscript,observer-pattern,Java,Events,Actionscript,Observer Pattern,我目前有一个Java Observer/Observable设置,在该设置中,我打开Observer.update(例如事件id)的对象参数中的某个字段,以确定如何处理可观察的通知 这将创建详细的代码,如: public void update (Observable o, Object arg) { if (arg instanceof Event) { switch (((Event)arg).getID()) { case EVENT_TYP

我目前有一个Java Observer/Observable设置,在该设置中,我打开Observer.update(例如事件id)的对象参数中的某个字段,以确定如何处理可观察的通知

这将创建详细的代码,如:

public void update (Observable o, Object arg) {
    if (arg instanceof Event) {
        switch (((Event)arg).getID()) {
            case EVENT_TYPE_A:
                // do stuff...
                break;
            case EVENT_TYPE_B:
                // do stuff...
                break;
            case EVENT_TYPE_C:
                // do stuff...
                break;
        }
    }
}
来自ActionScript背景,这让我觉得不必要的冗长……与其传递一个观察者的实例,我更愿意传递一个回调方法,由观察者(更具体地说,由一个子类)直接调用。但是,我不清楚如何确定应该在哪个对象上调用该方法(“拥有”该方法的类实例)

我可以传递对包含该方法的实例的引用,但这闻起来像糟糕的OOP


我找错树了吗?还是有一个干净的方法来实现这一点?

更干净的实现将涉及到将事件是否可以由观察者/可观察者处理的逻辑转移到实际的观察者/可观察者本身。似乎ActionScript给您留下了一个关于观察者模式的有趣想法。遵守(无双关语):

公共接口观察者{
公共作废更新(事件参数);
}
公开课活动{
公共int ID;
}
公共按钮实现观察器{
公共无效更新(事件参数){
开关(参数ID){
案例1://按钮处理类型1的事件
//做一些有用的事情;
打破
违约:
System.out.println(“按钮不处理ID为:“+arg.ID”的事件);
打破
}
}
}
公共ProgressBar实现了Observer{
公共无效更新(事件参数){
开关(参数ID){
案例2://ProgressBars处理类型2和类型3的事件
//做一些有用的事情;
打破
案例3:
//做一些其他有用的事情;
打破
违约:
System.out.println(“进度条不处理ID为“+arg.ID”的事件);
打破
}
}
}
公共课科目{
私有ArrayList AlluiControl;
公共注册控制(观察员控制){
添加(控件);
}
公共void updateControl(事件参数){
foreach(AlluiControl中的观察者控制){
//将事件传递给每个UI控件,并让事件决定是否可以理解event.ID
//主体的工作不是决定观察者是否适合处理事件。这不是观察者模式。
控制更新(arg);
}
}
}

这在左图中可能有点离题,但由于Java5和更高版本有泛型,传统的观察者和监听器模式似乎都有点过时。也就是说,类型是当今java的主要语言。具有整数ID的事件的存在主要是因为针对常量的switch语句非常有效——以可读性为代价,并且通常需要强制转换来执行任何有用的操作(您可能知道,如果ID=23,则对象必须是MouseEvent,但如果让编译器和运行时类型信息为您处理这一点,则会更好、更安全)。在现代JVM中的现代机器上,效率可能不值得

所以,如果你还没有与IDS和传统的观察者模式结婚,你可能会考虑这样的事情:

public abstract class Observer<T> {
  private final Class<T> type;

  protected Observer(Class<T> type) {
    this.type = type;
  }

  //implement this method;  if it returns false, the event (object) 
  //is "consumed" and no other observers should be called
  public abstract boolean onEvent(T instance);

  protected final boolean matches(Object obj) {
    return type.isInstance(obj);
  }

  Boolean maybeDispatch(Object o) {
    if (matches(o)) {
      return onEvent(type.cast(o));
    }
    return null;
  }
}
public class Bus {
  private final List<Observer<?>> observers = new ArrayList<Observer<?>>();

  public void registerObserver(Observer<?> observer) {
    observers.add(observer);
  }

  public <T> void onEvent(T t) {
    Boolean keepGoing;
    for (Observer<?> obs : observers) {
      keepGoing = obs.maybeDispatch(t);
      if (keepGoing != null && !keepGoing.booleanValue()) {
        break;
      }
    }
  }
}
公共抽象类观察者{
私有最终类类型;
受保护的观察者(类类型){
this.type=type;
}
//实现此方法;如果返回false,则事件(对象)
//被“消耗”,不应调用其他观察者
公共抽象布尔onEvent(T实例);
受保护的最终布尔匹配(对象obj){
返回类型。isInstance(obj);
}
布尔可能分布(对象o){
if(匹配(o)){
返回一个通风孔(类型铸造(o));
}
返回null;
}
}
这使我们(字面上)成为事件的一般观察者;我们打开传入对象的类型,如下所示:

public abstract class Observer<T> {
  private final Class<T> type;

  protected Observer(Class<T> type) {
    this.type = type;
  }

  //implement this method;  if it returns false, the event (object) 
  //is "consumed" and no other observers should be called
  public abstract boolean onEvent(T instance);

  protected final boolean matches(Object obj) {
    return type.isInstance(obj);
  }

  Boolean maybeDispatch(Object o) {
    if (matches(o)) {
      return onEvent(type.cast(o));
    }
    return null;
  }
}
public class Bus {
  private final List<Observer<?>> observers = new ArrayList<Observer<?>>();

  public void registerObserver(Observer<?> observer) {
    observers.add(observer);
  }

  public <T> void onEvent(T t) {
    Boolean keepGoing;
    for (Observer<?> obs : observers) {
      keepGoing = obs.maybeDispatch(t);
      if (keepGoing != null && !keepGoing.booleanValue()) {
        break;
      }
    }
  }
}
公共类总线{
私人最终名单>();
公共无效注册表观察者(观察者){
添加观察员(观察员);
}
公共无效事件(T){
布尔保持;
观察员(obs:观察员){
keepGoing=obs.maybeDispatch(t);
if(keepGoing!=null&!keepGoing.booleanValue()){
打破
}
}
}
}
结果代码的效率(略微)较低,但编写这种“观察者”的子类的可读性要大得多。它看起来不像传统的观察者模式,但在功能上是等效的


如果您还需要其他“活动”参数,您可以在两种类型上进行类似的逻辑参数化。

我看到了您的困境;这不是观察者模式。看,是的,这就是我现在所处的位置。我可以使用观察者事件处理程序中的开关。这只是一种与ActionScript稍有不同的模式;我看到了每种模式的优缺点。嗯,非常有趣…现在,我想继续使用Java的Observer,但这似乎是以后重新设计架构的一个很好的候选者。我仍然是一个Java noob(如果你没有猜到的话)泛型对我来说是新的,虽然我在集合框架中使用过它们。但我开始意识到它们带来的灵活性,同时仍然保持类型安全性和编译时的良好性。。。