c#设计模式系列:观察者模式(Observer Pattern)

引言

在现实生活中,处处可见观察者模式,例如,微信中的订阅号,订阅博客和QQ微博中关注好友,这些都属于观察者模式的应用。在这一章将分享我对观察者模式的理解,废话不多说了,直接进入今天的主题。

观察者模式的介绍

2.1 观察者模式的定义

   从生活中的例子可以看出,只要对订阅号进行关注的客户端,如果订阅号有什么更新,就会直接推送给订阅了的用户。从中,我们就可以得出观察者模式的定义。

观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己的行为。

2.2 观察者模式的结构图

1048776-20171130133356354-676034245

可以看出,在观察者模式的结构图有以下角色:

  • 抽象主题角色(Subject):抽象主题把所有观察者对象的引用保存在一个列表中,并提供增加和删除观察者对象的操作,抽象主题角色又叫做抽象被观察者角色,一般由抽象类或接口实现。
  • 抽象观察者角色(Observer):为所有具体观察者定义一个接口,在得到主题通知时更新自己,一般由抽象类或接口实现。
  • 具体主题角色(ConcreteSubject):实现抽象主题接口,具体主题角色又叫做具体被观察者角色。
  • 具体观察者角色(ConcreteObserver):实现抽象观察者角色所要求的接口,以便使自身状态与主题的状态相协调。

2.3观察者模式的实现

下面我们已抖音为例,当你刷抖音时候,看到一个很不错的小视频,就关注了这个作者,以后作者每次更新视频的时候,系统都会给关注他的粉丝推送新的消息,下面是我写的第一版实现代码:

  /// <summary>
    /// 作者
    /// </summary>
    public class OAuth
    {
        private List<Fans> list = new List<Fans>();
        public string name { get; set; }

        /// <summary>
        /// 新增一个粉丝
        /// </summary>
        /// <param name="add"></param>
        public void Add(Fans add)
        {
            list.Add(add);
        }
        /// <summary>
        /// 减少一个粉丝
        /// </summary>
        /// <param name="remove"></param>
        public void Remove(Fans remove)
        {
            list.Remove(remove);
        }
        public void Nofify()
        {
            foreach (Fans item in list)
            {
                item.Update();
            }
        }
    }
    /// <summary>
    /// 粉丝
    /// </summary>
    public class Fans
    {

        private string name;
        private OAuth sub;
        public Fans(string name, OAuth sub)
        {
            this.name = name;
            this.sub = sub;
        }
        public void Update()
        {
            Console.WriteLine("你好:{0},{1}发布了新的作品,点击查看",name,sub.name);
        }
    }

   /// <summary>
    /// 客户端
    /// </summary>
    class Program
    {
        static void Main(string[] args)
        {

            OAuth oauth = new OAuth();
            oauth.name = "小炒肉";
            Fans a = new Fans("青椒",oauth);
            Fans b = new Fans("胡萝卜",oauth);
            oauth.Add(a);
            oauth.Add(b);

            oauth.Nofify();

            Console.ReadLine();
        }
    }
    //结果显示
    你好:青椒,小炒肉发布了新的作品,点击查看
    你好:胡萝卜,小炒肉发布了新的作品,点击查看
View Code

看到这种代码我们首先想到的是 违反了面向对象的开发-封闭原则,其次是依赖倒转原则,类与类之间不应该相互依赖,而应该依赖与抽象,好了,我们得重新修改了,10分钟后第二版出来了

   public abstract  class Observer
    {
        protected string name;
        protected Subject sub;
        public Observer(string name, Subject sub)
        {
            this.name = name;
            this.sub = sub;
        }
        public abstract void Update();
    }

    public class Person : Observer
    {
        public Person(string name, Subject sub) : base(name, sub) { }

        public override void Update()
        {
            Console.WriteLine("你好:{0},{1}发布了新的作品,点击查看", name, sub.name);
        }
    }
 public abstract class Subject
    {
        public string name { get; set; }
        public abstract void Add(Observer ob);
        public abstract void Remove(Observer ob);
        public abstract void Notify();
    }
    public class Green : Subject
    {
        private List<Observer> list = new List<Observer>();
        public override void Add(Observer ob)
        {
            list.Add(ob);
        }
        public override void Notify()
        {
            foreach (var item in list)
            {
                item.Update();
            }
        }
        public override void Remove(Observer ob)
        {
            list.Remove(ob);
        }
    }
    /// <summary>
    /// 客户端
    /// </summary>
    class Program
    {
        static void Main(string[] args)
        {
            Subject ob = new Green();
            ob.name = "小炒肉";
            Observer a = new Person("青椒", ob);
            Observer b = new Person("胡萝卜", ob);
            ob.Add(a);
            ob.Add(b);
            ob.Notify();
            Console.ReadLine();
        }
    }
  ///结果
你好:青椒,小炒肉发布了新的作品,点击查看
你好:胡萝卜,小炒肉发布了新的作品,点击查看
View Code

  现在已经依赖接口编程,但是“抽象通知者”还是依赖 抽象观察者,也就是说,万一没有了抽象观察者这样的接口,我这通知的功能就完成不了,下面我们引入委托解耦实现通知者和观察者

    public class Person
    {
        protected string name;
        protected Subject sub;
        public Person(string name, Subject sub)
        {
            this.name = name;
            this.sub = sub;
        }
        public  void UpdateTP()
        {
            Console.WriteLine("你好:{0},{1}发布了新的作品,点击查看", name, sub.name);
        }
    }
    public delegate void EventHandler();
   public interface Subject
    {
        string name { get; set; }
         void Notify();
    }
    public class Green : Subject
    {

        public event EventHandler Update;
        public string name { get; set; }

        public void Notify()
        {
            Update();
        }
    }
    /// <summary>
    /// 客户端
    /// </summary>
    class Program
    {
        static void Main(string[] args)
        {
            Green hand = new Green();
            hand.name = "小王";
            Person per = new Person("青椒",hand);
            Person Ge = new Person("小炒肉", hand);
            hand.Update += new EventHandler(per.UpdateTP);
            hand.Update += new EventHandler(Ge.UpdateTP);

            hand.Notify();

            Console.ReadLine();
        }
    }
View Code

总结

在C#的event中,委托充当了抽象的Observer接口,而提供事件的对象充当了目标对象。委托是比抽象Observer接口更为松耦合的设计。

好了在次复习下,观察者模式的定义,观察者模式定义了一种一对多的关系,让多个观察者对象可以同时监听某一个主题对象,这个主题对象在发送状态改变时,会通知所有观察者对象,时它们能够自动更新自己

posted @ 2018-08-29 21:08  学无止境Time  阅读(394)  评论(0编辑  收藏  举报