设计模式学习(二)“观察者模式” (C#)
2021-05-08 21:29
标签:sub 定义 pen 关闭 监测 可扩展 style origin sed 开发一套气象监测应用,如图: 气象站,目前有三种装置,温度、湿度和气压感应装置。 WeatherData对象追踪气象站的数据,并更新到布告板,布告板(目前是三个:目前状况、气象统计、天气预报)用来显示目前的天气状况给用户。 目前的要求: 1.其中有三个方法分别获得气温、湿度和气压的数据。 2.一旦气象测量被更新,那么这个measurementsChanged()方法就会被调用。 3.一旦有新的数据,者三个布告板(暂时三个)就会马上更新。 4.可扩展,可以开发第三方的布告板。 错误在哪: 1.变化的地方需要封装。 2.布告板应该统一实现某个带有update方法的接口。 3.不应该针对实现编程,应该针对接口编程。 例子: 我们订阅公众号,公众号一旦有新文章就会发送给我们。 当我不再想看文章时,就取消订阅,这时就不会给我发送文章了。 只要公众号还在运营,就一直有人订阅或者取消订阅。 不过我们用的名词不一样,出版者改为主题(Subject),订阅者改为观察者(Observer) 观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者(dependents)都会收到通知并自动更新。 两个对象之间的松耦合就是,他们可以交互,但是不清楚对方太多细节。 观察者模式的Subject与Observers之间是松耦合,因为: 1.Subject对于Observer知道的唯一一件事情就是它实现了某个接口。 2.随时可以添加新的Observer。 3.新的Observer出现时,永远不需要更改Subject的代码。 4.我们可以独立的复用Subject或Observer。 5.改变任意的一方并不会影响另外一方。 交互对象之间应该尽可能的去实现松耦合设计。 接口们: WeatherData(subject): 其中一个布告板: ---------------------------------------------------------------------------------------------------------------------------------------------------------------- IObservable IObserver 先封装一下数据: WeatherData: 实现两个布告板: 测试程序: 设计模式学习(二)“观察者模式” (C#) 标签:sub 定义 pen 关闭 监测 可扩展 style origin sed 原文地址:http://www.cnblogs.com/cgzl/p/7624459.html《深入浅出设计模式》学习笔记第二章
需求:
初步设计
错误的实现:
什么是观察者模式 Observer Pattern
出版者(Publishers) + 订阅者(Subscribers) = 观察者模式(Observer Pattern)
观察者模式定义:
观察这模式关系图:
松耦合
设计原则
气象应用的具体设计:
C#实现:
namespace C02ObserverPattern.Raw.Bases
{
public interface ISubject
{
// 订阅
void RegisterObserver(IObserver observer);
// 取消订阅
void RemoveObserver(IObserver observer);
// 状态变化时,通知所有观察者
void NotifyObservers();
}
public interface IObserver
{
// 气象之变化时,subject会把这些值更新给observers
void Update(float temp, float humidity, float pressure);
}
public interface IDisplayElement
{
// 布告板显示
void Display();
}
}
namespace C02ObserverPattern.Raw
{
public class WeatherData: ISubject
{
private readonly HashSet
namespace C02ObserverPattern.Raw
{
public class CurrentConditionDisplay: IObserver, IDisplayElement
{
private float _temp, _humidity;
public CurrentConditionDisplay(ISubject weatherData)
{
weatherData.RegisterObserver(this);
}
public void Update(float temp, float humidity, float pressure)
{
_temp = temp;
_humidity = humidity;
Display();
}
// 这个布告板只显示温度和湿度
public void Display()
{
Console.WriteLine($"Current conditions:{_temp}℃ and {_humidity}% humidity");
}
}
}
测试程序:
namespace C02ObserverPattern
{
class Program
{
static void Main(string[] args)
{
WeatherData weatherData = new WeatherData();
CurrentConditionDisplay currentConditionDisplay = new CurrentConditionDisplay(weatherData);
StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData);
// XxxDisplay1 xxxDisplay1 = new XxxDisplay1(weatherData);
// XxxDisplay2 xxxDisplay2 = new XxxDisplay2(weatherData);
weatherData.SetMeasurements(10, 20, 30);
weatherData.SetMeasurements(14, 25, 36);
weatherData.SetMeasurements(40, 50, 60);
Console.ReadLine();
}
}
}
结果:
使用C#内置的Observer Pattern
namespace C02ObserverPattern.BuiltIn
{
public struct MyData
{
public float Temperature { get; }
public float Humidity { get; }
public float Pressure { get; }
public MyData(float temperature, float humidity, float pressure)
{
Temperature = temperature;
Humidity = humidity;
Pressure = pressure;
}
}
}
namespace C02ObserverPattern.BuiltIn
{
public class WeatherDataAlternative : IObservable
namespace C02ObserverPattern.BuiltIn
{
public class CurrentConditionDisplayAlternative : IObserver
namespace C02ObserverPattern.BuiltIn
{
public class StatisticsDisplayAlternative : IObserver
namespace C02ObserverPattern
{
class Program
{
static void Main(string[] args)
{
WeatherDataAlternative weatherDataAlternative = new WeatherDataAlternative();
CurrentConditionDisplayAlternative currentConditionDisplayAlternative = new CurrentConditionDisplayAlternative();
currentConditionDisplayAlternative.Subscribe(weatherDataAlternative);
StatisticsDisplayAlternative statisticsDisplayAlternative = new StatisticsDisplayAlternative();
statisticsDisplayAlternative.Subscribe(weatherDataAlternative);
weatherDataAlternative.NotifyMeasurementsChanged(new MyData(25, 75, 120));
Task.Delay(1000);
weatherDataAlternative.NotifyMeasurementsChanged(null);
Task.Delay(1000);
currentConditionDisplayAlternative.Unsubscribe();
weatherDataAlternative.NotifyMeasurementsChanged(new MyData(23, 45, 104));
weatherDataAlternative.WeatherStationClose();
Console.ReadLine();
}
}
}
下一篇:API验证
文章标题:设计模式学习(二)“观察者模式” (C#)
文章链接:http://soscw.com/index.php/essay/84108.html