Umbenennen implementierten Methoden für Beobachter-Muster in Java
-
27-09-2019 - |
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.
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
}