2016-07-11 3 views
0

私は観察者のパターンで学習して遊ぶプログラムを書いたが、正しく印刷されているデータに問題がある。ペーストの7-9行目のデータ入力を出力するはずですが、代わりに0,0,0を出力します。正しいデータが受信されないのはなぜですか?

メインクラス

public class ObserverPattern { 

    public static void main(String[] args) { 
     Subject weatherData = new Subject(); 
     weatherData.setTemp(81); 
     weatherData.setHumidity(14); 
     weatherData.setWindSpeed(8); 

     Observer johnsIpad = new Observer(weatherData); 

     weatherData.notifyObserver(); 

     System.out.println(johnsIpad.toString()); 
    } 

} 

Subjectクラス

import java.util.ArrayList; 

public class Subject { 

    // fields 
    ArrayList<Observer> observers; 
    public double temp; 
    public double humidity; 
    public double windSpeed; 

    // Constructor 
    public Subject() { 
     observers = new ArrayList<Observer>(); 
    } 

    // Observer pattern methods 
    public void register(Observer o) { 
     observers.add(o); 
    } 

    public void unregister(Observer o) { 
     observers.remove(observers.indexOf(o)); 
    } 

    public void notifyObserver() { 
     for (Observer observer : observers) { 
      observer.update(temp, humidity, windSpeed); 
     } 
    } 

    // set weather data 
    public void setTemp(double temp) { 
     this.temp = temp; 
    } 

    public void setHumidity(double humidity) { 
     this.humidity = humidity; 
    } 

    public void setWindSpeed(double windSpeed) { 
     this.windSpeed = windSpeed; 
    } 

} 

オブザーバークラス

public class Observer { 

    double temp; 
    double humidity; 
    double windSpeed; 

    Subject weatherData; 

    Observer(Subject weatherDataSource) { 
     weatherData = weatherDataSource; 
    } 

    public void update(double temp, double humidity, double windSpeed) { 
     this.temp = temp; 
     this.humidity = humidity; 
     this.windSpeed = windSpeed; 
    } 

    public String toString() { 
     return temp + "\n" + humidity + "\n" + windSpeed; 
    } 

} 

答えて

2

あなたは、件名にあなたのオブザーバーを登録したことがないので、notifyObserverを通知するための何のオブザーバーを持っていません。 forループ本体は決して実行されません。

追加:

weatherData.register(johnsIpad); 

あなたがnotifyObserver(weatherData)を呼び出す前に。

+0

あなたは正しいですか?私はそれをコンストラクタに追加しました。 sidenoteとして、あなたがやったやり方やコンストラクタの中で行うことは、異なる結果をもたらします。コンストラクタでは、それは自動的に毎回発生することになり、望ましくない可能性があります。しかし、それがコンストラクタになく、毎回それを望んでいなければ、それを登録するのを忘れるのは簡単でしょう。それはおそらくそれが最初に登録される頻度に依存します。 – Supetorus

+0

いいえ、コンストラクタに追加しないでください。私はこれが悪い考えであるいくつかの理由で上記にコメントしました。 –

+0

(私が「上記」と言うとき、私は[OPの回答](http://stackoverflow.com/a/38316898/3788176)を参照しています)。 –

0

この行をObserverクラスのコンストラクタに追加しました。

weatherData.register(this); 

これで機能します。それを私に指摘してくれてありがとう。

+0

クラスに 'Subject'参照が本当に必要ないということに注意してください。ガベージコレクションに影響する周期的な参照を作成します。 Observerクラスの責任を最小限に抑えることは、コンストラクタではなく、 'Observer'を' Subject'に外部的に登録することにより、より効果的です。 –

+0

さらに、これは* unsafe publication *の例です。完全に構築される前に、オブザーバへの参照を共有しています。これは一般に、特にスレッドの安全性に関する予測できない結果につながります。 –

+0

ねえ、良い点。私はちょうどそれをしました。cuz derek banasは、私が見ていたチュートリアルでそれをしました。 – Supetorus

関連する問題