[.Net 4.0]用4.0实现基于Push的Observer模式

在4.0里,微软为我们实现基于Push的观察者模式提供了原生支持:增加了IObserver<T>和IObservable<T>两个接口。

IObserver<T>: 表示接收通知(观察器)的类。

IObservable<T>:表示发送通知(提供程序)的类;

T :表示提供通知信息的类。

下面就应这几个接口来实现常用于解释观察者模式的模型-报纸订阅。

1.创建杂志

    class Magazine
    {
        private string m_Title;

        public string Title
        {
            get { return m_Title; }
            set { m_Title = value; }
        }
        private string m_Issue;

        public string Issue
        {
            get { return m_Issue; }
            set { m_Issue = value; }
        }

        public Magazine(string title, string issue)
        {
            m_Title = title;
            m_Issue = issue;
        }
    }


2. 接收通知的类即订阅者(这里随便取了哥名字叫Customer)
    class Customer : IObserver<Magazine>
    {
        private string m_Name;

        public string Name
        {
            get { return m_Name; }
            set { m_Name = value; }
        }

        public Customer(string name)
        {
            m_Name = name;
        }
        public void OnCompleted()
        {
            Console.WriteLine("订阅结束");
        }

        public void OnError(Exception error)
        {
            throw new NotImplementedException();
        }

        public void OnNext(Magazine magazine)
        {
            Console.WriteLine("{0}:新杂志来了!\r\n\t名称:{1}\t期号:{2}",m_Name, magazine.Title, magazine.Issue);
        }
    }

3.发送通知(提供程序)的类(报摊老板,这里假定这个老板很给力,垄断了报摊生意,全世界以后就他一个人卖报纸,不过他脾气也很怪异,随时都有可能不做生意)
class TheSeller :IObservable<Magazine>
    {
        private List<IObserver<Magazine>> m_Obervers = new List<IObserver<Magazine>>();

        private static readonly TheSeller m_Instance = new TheSeller();

        public static TheSeller Instance
        {
            get { return TheSeller.m_Instance; }
        }

        private TheSeller()
        {
        }
        public Magazine GetCurrentMagazine()
        {
            var magazine = new Magazine("测试杂志?", string.Format("第{0}期", IssueSimulator.GenerateIssue()));

            foreach (var observer in m_Obervers)
            {
                observer.OnNext(magazine);
            }

            return magazine;
        }
        public IDisposable Subscribe(IObserver<Magazine> observer)
        {
            m_Obervers.Add(observer);

            return observer as IDisposable;
        }

        public bool IsCrazy()
        {
            var result = new Random().Next(1, 10) == 5;

            if (result)
            {
                foreach (var observer in m_Obervers)
                {
                    observer.OnCompleted();
                }

            }
            return result;
        }
    }

4.其他辅助类型(IssueSimulator用生成模拟期号)
static class IssueSimulator
    {
        private static int m_Issue = 1;

        public static int GenerateIssue()
        {
            return m_Issue++;
        }
    }

5.调用代码
class Program
    {
        static void Main(string[] args)
        {
            var customer1 = new Customer("张三");
            var customer2 = new Customer("李四");

            TheSeller.Instance.Subscribe(customer1);
            TheSeller.Instance.Subscribe(customer2);

            while (!TheSeller.Instance.IsCrazy())
            {
                TheSeller.Instance.GetCurrentMagazine();
                Thread.Sleep(2000);
            }
        }
    }
posted @ 2011-02-19 05:26 FrogTan 阅读(180) 评论(0) 编辑 收藏