C# 观察者模式

编程要求

气象站将为我们提供温度、湿度和压力的数据,其中有四家天气预报软件公司进行了订阅,它们根据天气数据提供不同的天气服务。在本例中,四家公司要求气象局提供统一接口,并能实时数据更新。请补全右侧代码区begin至end间的代码,不可修改原代码。
在这里插入图片描述

输入格式:
输入第一行给出一个正整数n(n⩽10)表示数据更新的批次。随后n行,每行给出3个实数(温度、湿度和气压),其间以半角逗号分隔。

输出格式:
输出n次四家气象软件的输出。

输入样例:
3
80.0,65.0,30.4
82.0,70.0,29.2
78.0,90.0,29.2

输出样例:
现状: 80F度和65% 湿度
平均/最高/最低温度 = 80/80/80
预测: 气温正在上升
热指数 82.95535
现状: 82F度和70% 湿度
平均/最高/最低温度 = 81/82/80
预测: 气温正变得凉爽
热指数 86.90123
现状: 78F度和90% 湿度
平均/最高/最低温度 = 80/82/78
预测: 气温没有变化
热指数 83.64967

相关知识

概念
当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。

模式的结构
观察者模式的主要角色如下。

抽象主题(Subject)角色:也叫抽象目标类,它提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法。
具体主题(Concrete Subject)角色:也叫具体目标类,它实现抽象目标中的通知方法,当具体主题的内部状态发生改变时,通知所有注册过的观察者对象。
抽象观察者(Observer)角色:它是一个抽象类或接口,它包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用。
具体观察者(Concrete Observer)角色:实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态。
观察者模式的结构图如图 1 所示。
在这里插入图片描述

能解决的问题
一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。

最贴切的案例
杂志订阅,杂志是主题,观察者是订阅者。当出版新杂志时候,这个事件会自动通知所有的订阅者。

代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace F1
{
    class Program
    {
        static void Main(string[] args)
        {
            /********** Begin *********/
            int n = Convert.ToInt32(Console.ReadLine());
            WeatherData data = new WeatherData();
            data.RegisterObserver(new CurrentConditionsDisplay());
            data.RegisterObserver(new StatisticsDisplay());
            data.RegisterObserver(new ForecastDisplay());
            data.RegisterObserver(new HeatIndexDisplay());
            for (int i = 0; i < n; i++)
            {
                string str = Console.ReadLine();
                string[] arr = str.Split(',');
                data.setMeasurements(arr[0], arr[1], arr[2]);
            }

            /********** End *********/
        }
    }
    interface ISubject
    {
        void RegisterObserver(IObserver o);//注册观察者
        void RemoveObserver(IObserver o);//注销观察者
        void notifyObservers();///数据发生变化时,通知观察者
    }
    interface IObserver
    {
        void Update(float temp, float humidity, float pressure);
    }
    interface IDisplayElement
    {
        void display();
    }
    class WeatherData : ISubject
    {
        private float temperature;//温度
        private float humidity;//湿度
        private float pressure;//压力
        private List<IObserver> observers;//观察者列表,用List来存储所有的观察者
        public float Temperature { get { return temperature; } }
        public float Humidity { get { return humidity; } }
        public float Pressure { get { return pressure; } }
        public WeatherData()
        {
            observers = new List<IObserver>();
        }

        public void RegisterObserver(IObserver o)
        {
            /********** Begin *********/
               observers.Add(o);

            /********** End *********/
        }
        public void RemoveObserver(IObserver o)
        {
            int i = observers.IndexOf(o);
            /********** Begin *********/
              observers.RemoveAt(i);

            /********** End *********/
        }
        public void notifyObservers()
        {
            /********** Begin *********/
            foreach(IObserver o in observers)
                o.Update(temperature, humidity, pressure);

            /********** End *********/
        }

        public void setMeasurements(string temperature, string humidity, string pressure)
        {
            float temp;
            float.TryParse(temperature, out temp);
            this.temperature = temp;
            float.TryParse(humidity, out temp);
            this.humidity = temp;
            float.TryParse(pressure, out temp);
            this.pressure = temp;
            measurementsChanged();
        }
        public void measurementsChanged()
        {
            notifyObservers();
        }

    }
    class CurrentConditionsDisplay : IObserver, IDisplayElement
    {
        private float temperature;
        private float humidity;

        public void Update(float temperature, float humidity, float pressure)
        {
            this.temperature = temperature;
            this.humidity = humidity;
            display();
        }
        public void display()
        {
            Console.WriteLine("现状: " + temperature + "F度和" + humidity + "% 湿度");
        }
    }
    class ForecastDisplay : IObserver, IDisplayElement
    {
        private float currentPressure = 29.92f;
        private float lastPressure;
        public void Update(float temp, float humidity, float pressure)
        {
            lastPressure = currentPressure;
            currentPressure = pressure;
            display();
        }
        public void display()
        {
            Console.Write("预测: ");
            if (currentPressure > lastPressure) { Console.Write("气温正在上升\n"); }
            else if (currentPressure == lastPressure) { Console.Write("气温没有变化\n"); }
            else if (currentPressure < lastPressure) { Console.Write("气温正变得凉爽\n"); }
        }
    }
    class HeatIndexDisplay : IObserver, IDisplayElement
    {
        float heatIndex = 0.0f;
        public void Update(float t, float rh, float pressure)
        {
            heatIndex = computeHeatIndex(t, rh);
            display();
        }
        public void display()
        {
            Console.WriteLine("热指数 " + heatIndex);
        }
        private float computeHeatIndex(float t, float rh)
        {
            float index = (float)((16.923 + (0.185212 * t) + (5.37941 * rh) - (0.100254 * t * rh)
                + (0.00941695 * (t * t)) + (0.00728898 * (rh * rh))
                + (0.000345372 * (t * t * rh)) - (0.000814971 * (t * rh * rh)) +
                (0.0000102102 * (t * t * rh * rh)) - (0.000038646 * (t * t * t)) + (0.0000291583 *
                (rh * rh * rh)) + (0.00000142721 * (t * t * t * rh)) +
                (0.000000197483 * (t * rh * rh * rh)) - (0.0000000218429 * (t * t * t * rh * rh)) +
                0.000000000843296 * (t * t * rh * rh * rh)) -
                (0.0000000000481975 * (t * t * t * rh * rh * rh)));
            return index;
        }
    }
    class StatisticsDisplay : IObserver, IDisplayElement
    {
        private float maxTemp = 0.0f;
        private float minTemp = 200;
        private float tempSum = 0.0f;
        private int numReadings;
        public void display()
        {
            Console.WriteLine("平均/最高/最低温度 = " + (tempSum / numReadings) + "/" + maxTemp + "/" + minTemp);
        }

        public void Update(float temp, float humidity, float pressure)
        {
            tempSum += temp;
            numReadings++;
            if (temp > maxTemp)
            {
                maxTemp = temp;
            }
            if (temp < minTemp)
            {
                minTemp = temp;
            }
            display();
        }
    }
}

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值