Question

J'utilise l'interface de classe Observable / Observer en Java pour mettre en œuvre le modèle d'observateur. L'interface Observer nécessite la méthode mise à jour d'écraser (Observable o, Object arg).

Le problème est que j'observe un certain nombre de juste des classes, et ma méthode mise à jour () a obtenu très grand:

public class Foo implements Observer {
    ....

    public void update(Observable o, Object param) {
        if (o instanceof A) {
            // large chunk of code
            ...
        } else if (o instanceof B) {
            // large chunk of code
            ...
        }
            ...
        } else if (o instanceof H) {
            ...
        }
    }

}

Afin de séparer la méthode, je pense à étendre l'interface Observer avec par exemple AObserver interface, l'interface BObserver .. qui nécessite onAUpdate écrasement, onBUpdate .. respectivement. Cette méthode permettra également de déterminer facilement ce OBSERVABLES la classe observe basée sur les interfaces qu'il est mise en œuvre.

class Foo implements AObserver, BObserver {
    ....

    public void onAUpdate(Observable o, Object param) {
        if (o instanceof A) {
        // large chunk of code
        ...
    }

    public void onBUpdate(Observable o, Object param) {
        if (o instanceof B) {
        // large chunk of code
        ...
    }
}

Le problème est que si je hérité d'observateur, il me reste à mettre en œuvre la méthode mise à jour (). Je ne peux pas le renommer à onAUpdate ou un autre nom de mon choix.

Un conseil? Merci.

Était-ce utile?

La solution

Ici, je codé une mise en œuvre brute en utilisant l'observateur et les habitudes des visiteurs. Vous pouvez prendre cela comme une idée d'améliorer sur elle et de remplir chaque fois que vous voyez des trous.

public interface IObserver extends Observer {
    public void add(AbstractObservable observable, IObserverVisitor visitor);
    public void remove(AbstractObservable observable);
    public void removeAll();
}

public class Observer implements IObserver {

    Map<AbstractObservable, IObserverVisitor> observableMap =
            new HashMap<AbstractObservable, IObserverVisitor>();

    public void add(AbstractObservable observable, IObserverVisitor visitor) {
        observableMap.put(observable, visitor);
    }

    public void remove(AbstractObservable observable) {
        observableMap.remove(observable);
    }

    public void removeAll() {
        observableMap.clear();
    }

    public void update(Observable o, Object arg) {
        observableMap.get(o).visit(this, o, arg);
    }

}

public class AbstractObservable extends Observable{

    public synchronized void addObserver(IObserver o, IObserverVisitor visitor) {
        o.add(this, visitor);
        super.addObserver(o);
    }

    public synchronized void deleteObservers(IObserver o) {
        o.removeAll();
        super.deleteObservers();
    }

    public synchronized void deleteObserver(IObserver o) {
        o.remove(this);
        super.deleteObserver(o);
    }

    @Override
    public synchronized void deleteObserver(Observer o) {
        throw new UnsupportedOperationException();
    }

    @Override
    public synchronized void addObserver(Observer o) {
        throw new UnsupportedOperationException();
    }

    @Override
    public synchronized void deleteObservers() {
        throw new UnsupportedOperationException();
    }

    @Override
    public synchronized int countObservers() {
        return super.countObservers();
    }

    @Override
    public synchronized boolean hasChanged() {
        return super.hasChanged();
    }

    @Override
    public void notifyObservers() {
        super.notifyObservers();
    }

    @Override
    public void notifyObservers(Object arg) {
        super.notifyObservers(arg);
    }

    @Override
    protected synchronized void clearChanged() {
        super.clearChanged();
    }

    @Override
    protected synchronized void setChanged() {
        super.setChanged();
    }

}

public class Observable1 extends AbstractObservable {
    public void changeSomething() {
      setChanged();
      notifyObservers();
    }
}

public class Observable2 extends AbstractObservable {
    public void changeSomething() {
      setChanged();
      notifyObservers();
    }
}

public interface IObserverVisitor {
    void visit(IObserver obsrvr, Observable obsrvable, Object o);
}

public class ObserverVisitor1 implements IObserverVisitor{

    public void visit(IObserver obsrvr, Observable obsrvable, Object o) {
        System.out.println("updated one");
    }

}

public class ObserverVisitor2 implements IObserverVisitor{

    public void visit(IObserver obsrvr, Observable obsrvable, Object o) {
        System.out.println("updated two");
    }
}

public class ObserverTest {

    @Test
    public void testAnything() {
        Observable1 obsrvable1 = new Observable1();
        Observable2 obsrvable2 = new Observable2();

        Observer obsrvr = new Observer();
        obsrvable1.addObserver(obsrvr, new ObserverVisitor1());
        obsrvable2.addObserver(obsrvr, new ObserverVisitor2());

        obsrvable1.changeSomething();
        obsrvable2.changeSomething();
    }

}

J'espère que vous n'êtes pas perdu. :)

Autres conseils

Je suggère de créer une interface UpdateHandler pour effectuer le traitement pour un bloc de code donné. Chaque cas peut être poignée avec une carte.

Exemple de code suivante:

// Interface to implement for each case
public interface UpdateHandler {
    public void update(Observable source, Object data) ;
}

Ajoutez un champ d'instance à votre classe principale comme suit:

private Map<Class<?>, UpdateHandler> handlers = new HashMap<Class<?>, Update Handler>();

Créer une méthode pour avoir les gestionnaires initialisées

protected void initializeHandler() {
    handler.put(Integer.class, new IntegerUpdateHandler());
    handler.put(String.class, new StringUpdateHandler());
    ...
}

La méthode mises à jour se trouve simplement le gestionnaire approprié et envoyer l'appel

public void update(Observable source, Object data)
{
    UpdateHandler handler = handlers.get(data.getClass()) ;
    if (handler == null) 
    {
        // use a default handler ? throw an exception ? your choice ;)
    } else {
        handler.update(source, data) ;
    }
}

Cette implémentation vous permettra d'ajouter nouveau gestionnaire au besoin avec un minimum de changements.

Une autre application possible peut être faite sur la base de travaux antérieurs, juste une procédure en 3 étapes.

1) Modifier la déclaration du champ handlers.

Map<Class<?>, Class<? extends UpdateHandler>> handlers ;

2) modifier le mode d'initialisation

handlers.put(Integer.class, IntegerInputHandler.class);

3) modifie la principale méthode de mise à jour pour créer une nouvelle instance de l'application prévue UpdateHandler.

UpdateHandler handlerInstance = null ;
Class<? extends UpdateHandler> handler = null ;
handler = handlers.get(data.getClass()) ;
...
handlerInstance = handler.newInstance() ;
handlerInstance.update(source, data) ;

Déplacer les morceaux de code dans chaque condition à des méthodes bien nommé.

public void update(Observable o, Object param) {
    if (o instanceof A) {
         onAUpdate(o, param);
    }

    if (o instanceof B) {
         onBUpdate(o, param);
    }
}

public void onAUpdate(Observable o, Object param) {

    // large chunk of code
}

public void onABUpdate(Observable o, Object param) {

    // large chunk of code
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top