zoukankan      html  css  js  c++  java
  • .NET 4.0下的观察者模式

    下图是一个经典的观察者模式的结构。(图来源于wikipedia)

    观察者模式被定义为解决一个对象对多个对象的依赖问题。当一个对象的状态发生改变,它会自动通知其它依赖对象。关于该设计模式的介绍可以更多参考Terrylee的.NET设计模式(19):观察者模式(Observer Pattern)。这篇文章主要介绍在 .NET 4.0 怎么实现观察者模式。

    在.NET 4.0下位我们提供了两个观察者模式的底层接口:IObservable<T>和IObserver<T>。这两个接口定义如下:

    public interface IObservable<out T>
    {
        IDisposable Subscribe(IObserver observer);
    }
    public interface IObserver<in T>
    {
        void OnCompleted();
        void OnError(Exception error);
        void OnNext(T value);
    }

    IObserable就相当于是传统模式中的Subject,而IObserver就是订阅者。现在来演示一个新闻订阅的实例:当有被订阅的新闻站点有新文章发布时,发送信息通知它的订阅者。

    首先定义一个Article类,它就相当于是新闻网站中每一篇文章实体,保存着每篇文章的信息:

    class Article
    {
       public String Title;
       public DateTime Date;
       public String Author;
       public String Content;
    }

    然后是我们的订阅源——新闻站点:

    class News : IObservable<Article>
    {
        //用一个list来模拟保存站点中所有的文章
        private List<Article> articles = new List<Article>();
        //保存的所有的订阅者信息
        private List<IObserver<Article>> observers = new List<IObserver<Article>>();
    
        public IDisposable Subscribe(IObserver<Article> observer)
        {
            if (!this.observers.Contains(observer))
            {
                this.observers.Add(observer);
            }
            return new unsubscribe(observers, observer);
        }
    
        private class unsubscribe : IDisposable
        {
            private IObserver<Article> _observer;
            private List<IObserver<Article>> _observers;
    
            public unsubscribe(List<IObserver<Article>> observers, IObserver<Article> observer)
            {
                this._observer = observer;
                this._observers = observers;
            }
    
            public void Dispose()
            {
                if (this._observers != null && this._observers.Contains(this._observer))
                {
                    this._observers.Remove(this._observer);
                }
            }
        }
    
        //向订阅者发送通知
        private void Notify(Article article)
        {
            foreach (var item in this.observers)
            {
                item.OnNext(article);
            }
        }
        //当有新的文章发布时通知订阅者
        public void AddArticle(Article article)
        {
            this.articles.Add(article);
            this.Notify(article);
        }
    
    }

    下面来定义我们的订阅者。

    class Person : IObserver<Article>
    {
        //订阅者姓名
        String name;
        //保存订阅的新闻站点,方便以后取消订阅
        Dictionary<IObservable<Article>, IDisposable> sbscribes = new Dictionary<IObservable<Article>, IDisposable>();
    
        public Person(String name)
        {
            this.name = name;
        }
    
        public void Subscribe(IObservable<Article> news)
        {
            IDisposable unsub = news.Subscribe(this);
            sbscribes[news] = unsub;
        }
    
        public void UnSubscribe(IObservable<Article> news)
        {
            if (sbscribes.ContainsKey(news))
            {
                sbscribes[news].Dispose();
                sbscribes.Remove(news);
            }
        }
    
        //没有实现
        public void OnCompleted()
        {
            throw new NotImplementedException();
        }
    
        //当订阅中出现错误的处理没有实现
        public void OnError(Exception error)
        {
            throw new NotImplementedException();
        }
    
        //当有新的推送通知到达后的处理
        public void OnNext(Article value)
        {
            Console.WriteLine("One News: {0}",value.Title);
        }
    }

    下面我们看下运行时的代码:

    static void Main(string[] args)
    {
        News ChinaNews = new News();
        News EuropeNews = new News();
        Person person1 = new Person("heqichang");
        Person person2 = new Person("Jim");
    
        //我自己订阅了中国新闻和欧洲新闻
        person1.Subscribe(ChinaNews);
        person1.Subscribe(EuropeNews);
        //Jim订阅了欧洲新闻
        person2.Subscribe(EuropeNews);
    
        EuropeNews.AddArticle(new Article()
        {
            Title = "New title",
            Date = DateTime.Now.Date,
            Author = "heqichang",
            Content = "New content"
        });
    
    }

    现在我们很多人都应该使用着智能手机,我们可能经常在手机上收到一些应用发来的推送信息,这样的模式就跟我们的观察者模式很像。  

    扩展阅读:

    Reactive Extensions,简称Rx,是以IObserable<T>以及IObserver<T>为核心的,使用LINQ方式编程的.NET扩展库。 Rx = Observables + LINQ + Schedulers。有兴趣的可以搜索一下。

    以前我们订阅博客信息,依靠的都是拉文章,现在我们也可以使用“推”的方式来订阅。参看:PubSubHubbub

    参考链接:

    http://msdn.microsoft.com/zh-cn/library/dd783449(v=vs.100).aspx

  • 相关阅读:
    webpack4入门配置
    RequireJs的理解
    js一次控制 多个style样式
    vue中封装一个全局的弹窗js
    地理位置索引 2d索引
    索引属性 稀疏索引,定时索引
    索引属性 unique指定
    索引属性 name指定
    mongodb索引 全文索引使用限制
    mongodb索引 全文索引之相似度查询
  • 原文地址:https://www.cnblogs.com/heqichang/p/2653821.html
Copyright © 2011-2022 走看看