Frage

Ich bin mit der Klasse Observable / Observer-Schnittstelle in Java die Beobachter-Muster zu implementieren. Die Observer-Schnittstelle erfordert das Update (Observable o, Object arg) Methode überschrieben werden.

Das Problem ist, dass ich eine ganze Reihe von Klassen ich beobachten, und mein update () Methode hat sich als sehr groß geworden:

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

}

Um das Verfahren zu spalten, ich denke, die Observer-Schnittstelle beispielsweise mit der Erweiterung AObserver Schnittstelle, BObserver Schnittstelle .. das erfordert Überschreibungs onAUpdate, onBUpdate .. sind. Diese Methode wird es auch leicht, zu bestimmen, was Observablen die Klasse an dem Schnittstellen basiert Beobachten es zu implementieren.

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

Das Problem ist, dass, wenn ich Observer erben, ich habe immer noch das Update () -Methode zu implementieren. Ich kann es onAUpdate oder einen anderen Namen meiner Wahl nicht umbenannt werden.

Jede Beratung? Danke.

War es hilfreich?

Lösung

Hier codierte ich eine rohe Implementierung unter Verwendung von Beobachtern und Besuchermustern. Sie können als eine Idee, nehmen diese auf sie zu verbessern und zu füllen, wo Sie einige Löcher zu sehen.

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();
    }

}

Ich hoffe, dass Sie nicht verloren gehen. :)

Andere Tipps

Ich werde vorschlagen, eine UpdateHandler Schnittstelle erstellen, um die Verarbeitung für einen bestimmten Codeblock zu tun. Jeder Fall kann Griff mit einer Karte sein.

Beispielcode folgt:

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

In der Hauptklasse eine Instanz Feld wie folgt:

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

Erstellen Sie eine Methode, die Handler haben initialisierten

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

Die Updates Methode wird einfach die entsprechenden Handler finden und Versand den Anrufs

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

Diese Implementierung ermöglicht es Ihnen, neue Handler hinzufügen, wie mit minimalen Änderungen erforderlich.

Eine weitere mögliche Implementierung getan Basis auf der bisherigen Arbeit sein kann, nur ein 3-Schritt-Verfahren.

1) Ändern Sie die Deklaration des Handler Feld.

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

2) die Methode initialize ändern

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

3) die Hauptaktualisierungsmethode ändern, um eine neue Instanz der bereitgestellten UpdateHandler Umsetzung zu schaffen.

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

Verschieben Sie die Teile des Codes innerhalb jeder Bedingung entsprechend benannten Methoden.

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
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top