Универсальный обозреватель Java

У меня есть 2 объекта: Protocol а также Server, Первый уведомляет 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:

  • Метод onAction (AuthAction) типа Server должен переопределить или реализовать метод супертипа.
  • Параметр типа AuthAction скрывает тип AuthAction.

Итак, как реализовать мой "идеальный вариант" =)?

3 ответа

Решение

Вы можете сделать что-то вроде этого:

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!");
    }

В следующем синтаксисе

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) {
    }

}

Это набор IActionКонечный, неизменный и управляемый? Если это так, ваш наблюдатель больше похож на посетителя и требует перегрузки для каждого из известных действий.

Если набор IActions не все эти вещи, но звонящий знает, какой 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
    }
}

чья реализация будет выглядеть так же, как в предыдущем примере.

Другие вопросы по тегам