2010-11-24 71 views
5

我在Java中使用Observable類/ Observer接口來實現觀察者模式。 Observer接口需要覆蓋更新(Observable o,Object arg)方法。重命名Java中觀察者模式的實現方法

的問題是,我觀察了相當多的班,我的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接口..分別需要覆蓋onUpdate,onBUpdate ..這個方法還可以很容易地根據它實現的接口來確定類正在觀察的觀察對象。

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或我選擇的其他名稱。

有什麼建議嗎?謝謝。

回答

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

} 

我希望你不會丟失。 :)

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 
} 
+0

是否有可能爲每個Observable實現接口?當它實現AObserver,BObserver ...時,確定我的類感興趣的是什麼對象變得更加清晰,而不僅僅是一個普通的Observer – 2010-11-24 03:54:26

+0

這就是他最初做的。你只是建議取出塊來分離方法。該代碼仍然有味道。 – 2010-11-24 03:55:29

+0

他說這個問題是因爲「我的update()方法變得非常大」。 – crnlx 2010-11-24 04:01:33

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