I'm going through the (fantastic) book Head First Design Patterns and need some clarification on the observer pattern. The following little bit of code simulates a device (CurrentConditionDisplay) that listens for updates on weather patterns.
interfaces:
public interface ISubject { void RegisterObserver(IObserver obs); void RemoveObserver(IObserver obs); void NotifyObservers(); } public interface IDisplay { string Display(); } public interface IObserver { void Update(float temperature, float humidity, float pressure); }
Observer
public class CurrentConditionDisplay : IObserver, IDisplay { private float temperature; private float humidity; private float pressure; private ISubject weatherData; public CurrentConditionDisplay(ISubject weatherData) { this.weatherData = weatherData; this.weatherData.RegisterObserver(this); } public string Display() { StringBuilder sb = new StringBuilder(); sb.AppendLine("Welcome to Current Condition Display..."); sb.AppendLine(this.temperature.ToString()); sb.AppendLine(this.humidity.ToString()); sb.AppendLine(this.pressure.ToString()); return sb.ToString(); } public void Update(float temperature, float humidity, float pressure) { this.temperature = temperature; this.humidity = humidity; this.pressure = pressure; } }
Subject
public class WeatherData : ISubject { private List<IObserver> observersList; private float temperature; private float humidity; private float pressure; public WeatherData() { observersList = new List<IObserver>(); } public void RegisterObserver(IObserver obs) { observersList.Add(obs); } public void RemoveObserver(IObserver obs) { int index = observersList.IndexOf(obs); if (index >= 0) { observersList.RemoveAt(index); } } public void MeasurementsChanged() { Console.WriteLine("There is new data available..."); NotifyObservers(); } public void NotifyObservers() { foreach (IObserver observer in observersList) { observer.Update(temperature, humidity, pressure); } } public void SetMeasurements(float temperature, float humidity, float pressure) { this.temperature = temperature; this.humidity = humidity; this.pressure = pressure; MeasurementsChanged(); } }
To use these classes in my Program.cs I'm creating once instnce of WeatherData and passing that object as parameter to the constructor of CurrentConditionDisplay. A problem that I see with this current setup is that IObserver has one method Update which takes temperature, humidity, pressure as parameters. I see no guarantee that the Subject (WeatherData) has to have these fields in the first place. Should I add another interface or abstract base class to ensure that when SetMeasurements is called, all the fields being updated in that method are actually in the Observer?