2013-03-31 153 views
4

觀察者模式中的觀察者是否總是需要觀察相同類型的對象?一個觀察者觀察不同類型的不同類型的完全不相關的對象是否可以?Java中的觀察者模式 - 觀察者觀察不同的,不相關的類型或類?

示例 - Observer是CarDashBoard和Observable(s)是FuelTank,車速表,EngineThermometer,CarBattery等。觀察到的參數分別爲fuelLevel,speed,temperatureOfEngine,powerLevel。


如果我觀察多個不相關類型,那麼我將不得不使用instanceof()方法來檢查哪個通知的觀察者可觀察到的類。然而,看起來這是根據這個鏈接一個不錯的辦法 - http://www.javapractices.com/topic/TopicAction.do?Id=31

相關的instanceof另一個鏈接 - http://blog.joda.org/2007/01/java-language-dynamic-instanceof_7967.html

所以,我想我會使用的getClass()方法,然後再決定是什麼根據通過的Observable執行的操作。爲此目的使用getClass()是否安全?

有沒有其他的選擇?

+1

由於與'instanceof'相同的原因,'getClass()'是一個不好的方法。 –

+2

@MattBall - 請告訴我爲什麼getClass()會不好?我可以理解,instanceof()很糟糕,但不是爲什麼getClass會不好。 – SuperStar

+0

我的問題讓我懷疑Oracle的觀察者和觀察者的實現是否糟糕。你怎麼看 ? – SuperStar

回答

2

不使用instanceof的原因是這是一個使用多態的黑客。它會工作,但更好地提出一個更面向對象的解決方案。使用getClass也有同樣的問題。

我想我會創建多個觀察員,每個人爲FuelTank,車速表等,並讓他們更新CarDashboard。像這樣的東西。

public class CarDashboard 
{ 
    public int currentSpeed; 
    public int fuelPercentage;  
    //etc... 
} 

public class FuelObserver extends Observer 
{ 
    private CarDashboard dashboard; 

    public FuelObserver(CarDashboard dashboard) 
    { 
     this.dashboard = dashboard; 
    } 

    public void update(Observable fuelTank, Object fuelLevel) 
    { 
     this.dashboard.fuelPercentage = (int)fuelLevel; 
    } 
} 

//etc.. 
+0

我喜歡你的解決方案。如果觀察到的參數不是數字,而是複雜的對象,您的答案會改變嗎? – SuperStar

+0

看起來像這樣增加了MAIN Observer與其每個可觀察對象之間的耦合。 – SuperStar

+0

您正在getInstance中混合get和setting行爲。此外,靜態方法內的this.dashboard似乎是錯誤的。核心答案的立場,但getInstance方法不添加任何東西,並教我不好的風格。 – Joeblade

3

您可以使用多態性。例如,假設你有一個擴展Observable一個抽象類:

import java.util.Observable; 

public abstract class DashboardDataSource extends Observable { 

    public abstract int getLevel(); 
} 

然後,你必須從DashboardDataSource繼承兩個類(其實你有很多,你需要,我只是用兩個爲例) :

public class FuelLevel extends DashboardDataSource { 

    public void saySomething(){ 
     setChanged(); 
     notifyObservers(); 
    } 
    @Override 
    public int getLevel() { 
     // TODO Auto-generated method stub 
     return 50; 
    } 
} 

而且

public class BatteryLevel extends DashboardDataSource { 

    public void saySomething(){ 
     setChanged(); 
     notifyObservers(); 
    } 

    @Override 
    public int getLevel() { 
     // TODO Auto-generated method stub 
     return 20; 
    } 
} 

然後,您可以有一個Dashboard像這樣:

public class Dashboard implements Observer { 

    @Override 
    public void update(Observable o, Object arg) { 
     DashboardDataSource d = (DashboardDataSource) o; 
     System.out.println (d.getLevel()); 

    } 
} 

在這種情況下,你只投了Observable oDashboardDataSource並調用其抽象方法的實現,這將是具體到任何DashboardDataSource正在通知您Dashboard(在這個例子中FuelLevelBatteryLevel

+0

我也喜歡你的解決方案。如果觀察到的參數不是數字,而是複雜的對象,您的答案會改變嗎? – SuperStar

+0

不,答案依然存在。如果你注意到'public void update(Observable o,Object arg)'的第二個參數''是'Object',這意味着你可以傳遞任何類型的對象作爲'notifyObservers(Object arg)'中的一個參數,然後在'update'中將其轉換爲相同的類型。或者,您的抽象方法的實現可以返回您選擇的對象。所以,而不是'int'它可以返回一個自定義類型。 – Bizmarck