Question

I have 2 object: Protocol and Server. The first one is notifying Server with different objects and Server should perform action depending on type of object. So, perfect option for me is:

// 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);
   // ...
}

So i decided that it is a job for observer pattern.

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

Errors are in Server:

  • The method onAction(AuthAction) of type Server must override or implement a supertype method
  • The type parameter AuthAction is hiding the type AuthAction

So, how to implement my "perfect option" =)?

Was it helpful?

Solution 3

You can do something like this:

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

OTHER TIPS

In the following syntax

public <AuthAction> void onAction(AuthAction action) {

the expression AuthAction is a type variable, not a type argument. The code above is equivalent to

public <T> void onAction(T action) {

So you can therefore see how your Server class is not implementing IObserver's method. I would instead make IObserver a generic interface and implement it like so

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

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

}

Is the set of IActions finite, unchanging, and manageable? If so, your Observer is more like a Visitor and requires an overload for every one of the known actions.

If the set of IActions is not all of those things, but the caller knows what kind of IAction is being passed in statically, your IObserver interface as defined is correct. That is, an implementer of the interface (such as Server) should dynamically react to the specific IAction class, using any of a number of extremely ugly choices in Java to do so.

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

I don't think that buys you very much.

If the caller does not know which IAction is going to be used at runtime, then your only choice is

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

whose implementation will look the same as in the previous example.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top