zoukankan      html  css  js  c++  java
  • 设计模式——Observe模式

          今天学习了下观察者模式,在软件设计过程中,常常有类似这样的情况:许多部分(对象)与某一部分(对象)之间有种状态的依赖关系,即某一对象的状态发生改变时,要通知到所有的对象。比如:有一个天气预报观察站A,许多网站向它订阅了(通过某些协议)天气提供服务,当天气预报观察站A得到了最新天气信息时,就会通知到所有与它订阅过的网站,所有订阅过天气预报服务的网站就会实时更新天气信息;某一天,有另外一家观察站,设备更先进,信息更准确,价格更便宜,于是这些网站中某一个网站退订了观察站A的服务了,当观察站A再有信息更新的时候,只会通知到当前订阅的所有网站(不包括刚退订的网站)。这就是观察者模式,此例中,这些订阅天气预报的网站就充当了观察者角色。本文就主要关注如何实现这样的订阅服务:

          首先,我们假设所有提供服务的机构都属于一个机构统一管理(这个机构提供所有的服务,如天气预报、杂志订阅……),将它抽象出来,定义一个抽象的提供者类Provider,包含订阅、退订、更新时通知所有订阅者三个方法,类关系视图如下所示:

    各部分实现如下所示:

    View Code
        public abstract class Provider
        {
            protected List<ICustomer> customer = new List<ICustomer>();
    
            //向使用者提供订阅方法(渠道)
            public void AddCustomer(ICustomer cus)
            {
                customer.Add(cus);
            }
            //向使用者提供退订方法(渠道)
            public void RemoveCustomer(ICustomer cus)
            {
                customer.Remove(cus);
            }
            //通知订阅者
            public abstract void Update();
        }

         再定义一个模拟观察站A(WeatherProvider)继承自抽象的提供者(Provider),观察站A(WeatherProvider)继承来自提供者(Provider)的订阅、退订方法,并实现了更新时通知订阅者的方法,如下:

    View Code
       public class WeatherProvider:Provider
        {
            //提供天气预报的观察站名
            private string providerName;        
            //气温
            private string temperature;
    
            public string Temperature
            {
                get { return temperature; }
                set { temperature = value; }
            }
    
            public string ProviderName
            {
                get { return providerName; }
                set { providerName = value; }
            }
    
            public WeatherProvider(string name, string temp)
            {
                this.providerName = name;
                this.temperature = temp;
            }
    
            //通知所有订阅者
            public override void Update()
            {
                foreach (ICustomer cus in this.customer)
                {
                    cus.SendMessage(providerName, temperature);
                }
            }
        }

          现在我们模拟一些用户群体,每个用户都必须要实现下从提供服务处获取服务数据的方法(本文比如:只提供观察站名和当前气温),为了所有订阅者统一管理,定义一个接口:

    View Code
        public interface ICustomer
        {
            void SendMessage(string providerName,string temp);
        }

         此接口规定所有订阅者接受更新天气的方法。所有订阅者必须继承自此接口,规定必须实现接受更新天气的方法:

    View Code
       public class Customer:ICustomer
        {
            public Customer(string name)
            {
                this.name = name;
            }
    
            public string name { get; set; }
    
            public void SendMessage(string providerName, string temp)
            {
                Console.WriteLine("Hello! " + this.name + ", We are " + providerName + " , the temperrature is " + temp + "\n");
            }
        }

        观察者模式使用演示:

    View Code
       class Program
        {
            static void Main(string[] args)
            {
                //可以扩展出不同等级用户提供不同的服务内容
                ICustomer customerA = new Customer("腾讯网");
                ICustomer customerB = new Customer("新浪网");
    
                //可以扩展出除天气预报外不同提供服务机构
                Provider provider = new WeatherProvider("国家天气预报观察站", "10");
    
                //订阅
                provider.AddCustomer(customerA);
                provider.AddCustomer(customerB);
    
                provider.Update();
    
                Console.WriteLine("——————————————————————");
    
                //退订
                provider.RemoveCustomer(customerA);
                provider.Update();
    
                Console.ReadKey();
            }
        }

        程序运行结果:

         欢迎大牛们多多指点!

  • 相关阅读:
    同步类容器和并发类容器
    T4模板生成自定义的实体类
    C# UrlEncode 编码
    PLSQL快速生成增删改查语句
    Oracle 检查星期只能是1-7的数字不能重复
    PLSQL 插入数据无响应
    C# DataTable 排序
    C# 获取程序集信息
    C# 调用WinRAR解压缩文件
    DataTable 获取一列最大值并修改
  • 原文地址:https://www.cnblogs.com/yangyp/p/2807432.html
Copyright © 2011-2022 走看看