woo*_*gie 5 c# design-patterns observer-pattern
我正在阅读(出色的)书,Head First Design Patterns并且需要对观察者模式进行一些说明。下面的一些代码模拟了一个侦听天气模式更新的设备(CurrentConditionDisplay)。
接口:
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);
}
Run Code Online (Sandbox Code Playgroud)
观察者
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;
}
}
Run Code Online (Sandbox Code Playgroud)
学科
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();
}
}
Run Code Online (Sandbox Code Playgroud)
要在Program.cs中使用这些类,我需要创建一次实例WeatherData并将该对象作为参数传递给的构造函数CurrentConditionDisplay。我在当前设置中看到的一个问题是,IObserver有一种方法将Update其temperature, humidity, pressure作为参数。我看不到主题(WeatherData)必须首先具有这些字段。我应该添加另一个接口或抽象基类以确保在SetMeasurements调用时,该方法中要更新的所有字段实际上都在Observer吗?
我和你有同样的感觉......有一个相当通用的听起来IObserver界面有一个特定的方法签名,实际上只适用于观察WeatherData感觉恶心的时候!
我更愿意有这样的东西:
public interface IObserver<T>
{
void Update(T updatedData);
}
Run Code Online (Sandbox Code Playgroud)
对于一个看起来像这样的观察者(这里剪掉了一些额外的代码):
public class CurrentConditionDisplay : IObserver<WeatherUpdate>, IDisplay
{
public CurrentConditionDisplay(ISubject<WeatherUpdate> weatherData)
{
this.weatherData = weatherData;
this.weatherData.RegisterObserver(this);
}
public void Update(WeatherUpdate update)
{
this.temperature = update.Temperature;
this.humidity = update.Humidity;
this.pressure = update.Pressure;
}
}
Run Code Online (Sandbox Code Playgroud)
为了让自己清楚,我的通用T是IObserver<T>一个封装天气更新的对象:
public WeatherUpdate
{
public float Temperature;
public float Humidity;
public float Pressure;
}
Run Code Online (Sandbox Code Playgroud)
并且还ISubject必须更改为包含通用参数:
public interface ISubject<T>
{
void RegisterObserver(IObserver<T> obs);
void RemoveObserver(IObserver<T> obs);
void NotifyObservers();
}
Run Code Online (Sandbox Code Playgroud)