有这么一个项目,气象局发布温度,湿度,空气压力等数据,分别在不同的地方显示。这样的情况适合用观察者模式,观察者模式变化的是观察者,观察者数量不固定,所以要封装观察者。 把观察者设计成一个接口
public interface IObserver
{
void Update(double temperature, double humidity, double pressure);
}
为方便显示,再设计一个显示接口
public interface IDisplayElement
{
void Display();
}
主题接口设计成这样
public interface ISubject
{
IList<WeatherTest.IObserver> Observers { get; set; }
void Register(IObserver observer);
void Remove(IObserver observer);
void NotifyObservers();
}
currentconditions继承观察者接口
public class CurrentConditions : IObserver,IDisplayElement
{
private double _temperature;
private double _humidity;
private double _pressure;
public void Display()
{
Console.WriteLine($"当前环境:温度{_temperature} 湿度{_humidity}");
}
public void Update(double temperature, double humidity, double pressure)
{
_temperature = temperature;
_humidity = humidity;
_pressure = pressure;
Display();
}
}
Forecast也继承观察者接口
public class Forecast : IObserver,IDisplayElement
{
private double _temperature;
private double _humidity;
private double _pressure;
public void Display()
{
Console.WriteLine($"天气预报:明天温度{_temperature} 明天湿度{_humidity}");
}
public void Update(double temperature, double humidity, double pressure)
{
_temperature = temperature;
_humidity = humidity;
Display();
}
}
WeatherData从主题接口继承,为代码实现起来表现更优雅一些,重载了运算符+和-
public class WeatherData : ISubject
{
private IList<IObserver> observers;
private double _temperature;
private double _humidity;
private double _pressure;
public IList<IObserver> Observers { get => observers; set => observers = value; }
public WeatherData()
{
observers = new List<IObserver>();
}
public void NotifyObservers()
{
foreach(IObserver o in Observers)
{
o.Update(_temperature, _humidity, _pressure);
}
}
public void Register(IObserver observer)
{
Observers.Add(observer);
}
public void Remove(IObserver observer)
{
Observers.Remove(observer);
}
public static WeatherData operator +(WeatherData lhs,IObserver rhs)
{
lhs.Register(rhs);
return lhs;
}
public static WeatherData operator -(WeatherData lhs,IObserver rhs)
{
lhs.Remove(rhs);
return lhs;
}
public void SetMeasurements(double temperature,double humidity,double pressure)
{
_temperature = temperature;
_humidity = humidity;
_pressure = pressure;
NotifyObservers();
}
}
现在可以实现看看
static void Main(string[] args)
{
WeatherData weather = new WeatherData();
CurrentConditions current = new CurrentConditions();
Forecast forecast = new Forecast();
Console.WriteLine($"=====================>关联观察者");
weather += current;
weather += forecast;
Console.WriteLine($"=====================>设置温湿度");
weather.SetMeasurements(23, 35, 20);
Console.WriteLine($"=====================>移去一个当前环境观察者");
weather -= current;
weather.SetMeasurements(20, 20, 20);
Console.WriteLine($"=====================>运行结束");
Console.ReadLine();
}
结果如图显示,设计是成功的。
用C#的事件也可以实现观察者模式,把WeatherData封装成继承EventArgs的类,也很简单。