首页 > .NET, 设计模式 > .NET 4.0下的观察者模式

.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



2 Comments

  1. #1 sdj @ 2012-09-07 14:59

    原来如此。

    Reply

    • Qichang He @ 2012-09-15 11:13

      欢迎来访!

      Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

无觅相关文章插件,快速提升流量