Java通用观察者

时间:2014-01-27 19:06:20

标签: java generics observer-pattern

我有2个对象:ProtocolServer。第一个是通知Server不同的对象,Server应该根据对象的类型执行操作。所以,对我来说完美的选择是:

// Server.java
public Server implements IObserver {
    public void onAction(ActionObjectOne o) {
        //do magic
    }
    public void onAction(ActionObjectTwo o) {
        //do magic
    }
    ....
}

// Protocol.java
public Protocol extends AObservable {
   // ....
   notifyObservers(ActionObjectOne one);
   // ...
}

所以我认为这是观察者模式的工作。

public interface IObserver {
    <T extends IAction> void onAction(T action);
}

public class Server implements IObserver {
    @Override
    public <AuthAction> void onAction(AuthAction action) {
        // HERE IS A PROBLEM
    }
}

public class AuthAction extends Action; // Action implements IAction - a flag-interface

错误在Server

  • Server类型的onAction(AuthAction)方法必须覆盖或 实现超类型方法
  • 类型参数AuthAction隐藏类型AuthAction

那么,如何实现我的“完美选择”=)?

3 个答案:

答案 0 :(得分:1)

使用以下语法

public <AuthAction> void onAction(AuthAction action) {

表达式AuthAction是一个类型变量,而不是类型参数。上面的代码相当于

public <T> void onAction(T action) {

因此,您可以看到您的Server课程没有实现IObserver的方法。我会改为使IObserver成为通用接口并像这样实现它

public interface IObserver<T extends IAction> {
    void onAction(T action);
}

class Server implements IObserver<AuthAction> {
    @Override
    public  void onAction(AuthAction action) {
    }

}

答案 1 :(得分:0)

您可以这样做:

public void update(Observable o, Object arg) {
    try {
        Method update = getClass().getMethod("onAction", arg.getClass());
        update.invoke(this, arg);
    } catch (NoSuchMethodException e) {
        LOGGER.error("No onAction for <" + arg.getClass().getSimpleName() + "> action.");
        LOGGER.catching(e);
    } catch (Exception e) {
        LOGGER.catching(e);
    }
}

and then:

public void onAction (AuthAction action) {
        System.out.println("New user incoming!");
    }

答案 2 :(得分:0)

IAction的集合是有限的,不变的,可管理的吗?如果是这样,您的Observer更像是一个访问者,并且需要为每个已知操作重载。

如果IAction的集合并非所有这些内容,但调用者知道静态传递了哪种IAction,那么您定义的IObserver接口是正确的。也就是说,接口的实现者(例如Server)应该动态地对特定的IAction类做出反应,使用Java中的任何一些非常丑陋的选择来做如此。

public interface IObserver {
    void < T extends IAction > onAction( T action );
}
public class Server implements IObserver {
    @Override public void < T extends IAction > onAction( T action ) {
        // ugliness, e.g. if-ladders based on instanceof
    }
}

我认为这不会给你买得太多。

如果调用者不知道在运行时将使用哪个IAction,那么您唯一的选择是

public interface IObserver {
    void onAction( IAction action );
}
public class Server implements IObserver {
    @Override public void onAction( IAction action ) {
        // ugliness, e.g. if-ladders based on instanceof
    }
}

其实现与前一个示例中的实现相同。