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?
WeatherDatahavetemperature, humidity, pressureas private fields. The Observer and Subject have no common interface (to share those fields that are udpated).