Переименование реализованных методов для шаблона Observer в Java - PullRequest
5 голосов
/ 24 ноября 2010

Я использую интерфейс Observable class / Observer в Java для реализации шаблона наблюдателя.Интерфейс Observer требует перезаписи метода update (Observable o, Object arg).

Проблема в том, что я наблюдаю достаточное количество классов, и мой метод update () стал очень большим:

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

}

Чтобы разделить метод, я подумываю о расширении интерфейса Observer, например, интерфейсом AObserver, интерфейсом BObserver ... который требует перезаписи onAUpdate, onBUpdate .. соответственно.Этот метод также позволит легко определить, какие Observables наблюдает класс на основе интерфейсов, которые он реализует.

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

Проблема в том, что если я наследую Observer, мне все равно придется реализовать метод update (),Я не могу переименовать его в onAUpdate или в другое имя по своему выбору.

Любой совет?Спасибо.

Ответы [ 3 ]

3 голосов
/ 24 ноября 2010

Я предлагаю создать интерфейс UpdateHandler для обработки любого данного блока кода. Каждый случай может быть обработан картой.

Пример кода следующий:

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

Добавьте поле экземпляра в ваш основной класс следующим образом:

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

Создать метод для инициализации обработчиков

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

Метод обновлений просто найдет соответствующий обработчик и отправит вызов

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

Эта реализация позволит вам добавлять новый обработчик по мере необходимости с минимальными изменениями.

Другая возможная реализация может быть реализована на основе предыдущей работы, всего лишь 3 шага.

1) Изменить объявление поля обработчиков.

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

2) изменить метод инициализации

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

3) изменить основной метод обновления, чтобы создать новый экземпляр предоставленной реализации UpdateHandler.

UpdateHandler handlerInstance = null ;
Class<? extends UpdateHandler> handler = null ;
handler = handlers.get(data.getClass()) ;
...
handlerInstance = handler.newInstance() ;
handlerInstance.update(source, data) ;
1 голос
/ 24 ноября 2010

Здесь я кодировал сырую реализацию, используя шаблон наблюдателя и посетителя.Вы можете принять это как идею, чтобы улучшить его и заполнить, где вы видите некоторые дыры.

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

}

Надеюсь, вы не потерялись.:)

1 голос
/ 24 ноября 2010

Перемещение фрагментов кода в каждом условии в методы с соответствующим именем.

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