5

オブザーバーパターンを実装するために、JavaのObservableクラス/オブザーバーインターフェイスを使用しています。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) {
            ...
        }
    }

}

メソッドを分割するために、オブザーバーインターフェイスを拡張することを考えています。たとえば、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または選択した他の名前に名前を変更できません。

何かアドバイス?ありがとう。

4

3 に答える 3

3

特定のコードブロックの処理を行うために、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) ;
于 2010-11-24T04:22:44.333 に答える
1

ここでは、オブザーバーとビジターパターンを使用して生の実装をコーディングしました。あなたはそれを強化し、あなたがいくつかの穴を見るところならどこでも埋めるためのアイデアとしてこれをとることができます。

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

}

あなたが迷子にならないことを願っています。:)

于 2010-11-24T06:17:59.303 に答える
1

各条件内のコードのチャンクを適切な名前のメソッドに移動します。

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
}
于 2010-11-24T03:48:13.660 に答える