• 观察者模式(12)


    今天我们来讲一下观察者模式。还是老样子,给大家一个案例。

    一、案例

    在我们怀念的学生时代,我们会有这么一个现象,当在教室里上自习的时候,让一个同学把风,我们在教室里玩,当老师来的时候,让那个同学给我们说一声。

    好,下面我们就用简单的控制台应用程序来实现上述的场景(一个把风的同学,两个玩耍的同学)

     1     /// <summary>
     2     /// 把风同学类
     3     /// </summary>
     4     class Secretary
     5     {
     6         //有几个同学请把风的帮忙,于是就给集合增加几个对象
     7         private IList<Observer> obs = new List<Observer>();
     8         private string _action;
     9 
    10         public void Attach(Observer ob)
    11         {
    12             obs.Add(ob);
    13         }
    14 
    15         /// <summary>
    16         /// 老师回来时,给所有登记的同学们发通知。
    17         /// </summary>
    18         public void Notify()
    19         {
    20             foreach (var ob in obs)
    21             {
    22                 ob.Update();
    23             }
    24         }
    25         /// <summary>
    26         /// 状态
    27         /// </summary>
    28         public string SecretoryAction
    29         {
    30             get { return _action; }
    31             set { _action = value; }
    32         }
    33     }
    34 
    35     /// <summary>
    36     /// 玩耍的同学类
    37     /// </summary>
    38     class Observer
    39     {
    40         private string name;
    41         private Secretary sub;
    42 
    43         public Observer(string name, Secretary sub)
    44         {
    45             this.name = name;
    46             this.sub = sub;
    47         }
    48         /// <summary>
    49         /// 得到把风的通知
    50         /// </summary>
    51         public void Update()
    52         {
    53             Console.WriteLine($"{sub.SecretoryAction}{name}别玩游戏了");
    54         }
    55     }

    客户端:

     1         public static void Main()
     2         {
     3             //把风的
     4             Secretary s = new Secretary();
     5             //小王同学
     6             Observer ob1 = new Observer("小王", s);
     7             //小李同学
     8             Observer ob2 = new Observer("小李", s);
     9             //把风的记下两位同学
    10             s.Attach(ob1);
    11             s.Attach(ob2);
    12             //发现老师来了
    13             s.SecretoryAction = "老师回来了!";
    14             //通知两个同学
    15             s.Notify();
    16             Console.ReadKey();
    17         }

    嗯,上述代码我们发现了一个问题,就是 把风的这个同学的类 和 玩耍的同学的类,耦合性太强了。把风类需要增加玩耍的同学,同学类需要把风的通知。

    这么强的耦合,如果我们需要添加一个同学进来,那两边都需要修改了,如果还要通知唱歌同学老师来了,咋办?这其实违背了设计的两个原则,开放-封闭原则,依赖倒转原则。

    我们的程序都应该依赖于抽象,而不是相互依赖。

    二、演绎

    1、第一步演绎

    好,下面我们来修改一下上述的代码。增加一个抽象的观察者类

     1     /// <summary>
     2     /// 抽象的观察者
     3     /// </summary>
     4     public abstract class Observer
     5     {
     6         protected string name;
     7         protected Secretary sub;
     8 
     9         public Observer(string name, Secretary sub)
    10         {
    11             this.name = name;
    12             this.sub = sub;
    13         }
    14 
    15         public abstract void Update();
    16     }

    让具体的观察者继承这个抽象类

     1     /// <summary>
     2     /// 具体的观察者1(玩游戏的)
     3     /// </summary>
     4     public class Observer1 : Observer
     5     {
     6         public Observer1(string name, Secretary sub) : base(name, sub)
     7         {
     8         }
     9 
    10         public override void Update()
    11         {
    12             Console.WriteLine($"{sub.SecretoryAction}{name},别唱歌了。");
    13         }
    14     }
    15     /// <summary>
    16     /// 具体的观察者2(唱歌的)
    17     /// </summary>
    18     public class Observer2 : Observer
    19     {
    20         public Observer2(string name, Secretary sub) : base(name, sub)
    21         {
    22         }
    23 
    24         public override void Update()
    25         {
    26             Console.WriteLine($"{sub.SecretoryAction}{name},别玩游戏了。");
    27         }
    28     }

    把风同学类的代码基本不变

     1     /// <summary>
     2     /// 把风同学类
     3     /// </summary>
     4     public class Secretary
     5     {
     6         //有几个同学请把风的帮忙,于是就给集合增加几个对象
     7         private IList<Observer> obs = new List<Observer>();
     8         private string _action;
     9 
    10         public void Attach(Observer ob)
    11         {
    12             obs.Add(ob);
    13         }
    14 
    15         /// <summary>
    16         /// 老师回来时,给所有登记的同学们发通知。
    17         /// </summary>
    18         public void Notify()
    19         {
    20             foreach (var ob in obs)
    21             {
    22                 ob.Update();
    23             }
    24         }
    25         /// <summary>
    26         /// 状态
    27         /// </summary>
    28         public string SecretoryAction
    29         {
    30             get { return _action; }
    31             set { _action = value; }
    32         }
    33     }

    客户端调用

     1         public static void Main()
     2         {
     3             //把风的
     4             Secretary s = new Secretary();
     5             //玩耍小王同学
     6             Observer ob1 = new Observer1("小王", s);
     7             //玩耍小李同学
     8             Observer ob2 = new Observer1("小李", s);
     9             //玩耍小李同学
    10             Observer ob3 = new Observer2("小张", s);
    11             //把风的记下三位同学
    12             s.Attach(ob1);
    13             s.Attach(ob2);
    14             s.Attach(ob3);
    15             //发现老师来了
    16             s.SecretoryAction = "老师回来了!";
    17             //通知三位同学
    18             s.Notify();
    19             Console.ReadKey();
    20         }

    2、第二步演绎

    既然观察者我们抽象出一个抽象类来了,那么我们仔细观察一下,把风的同学这个类是一个具体的类,也可以抽象出来。还有,如果哪个同学跟把风的那个同学闹矛盾了,可以不给他通知了,嘿嘿。所以可以加一个删除方法。好了,看一下代码吧

     1     /// <summary>
     2     /// 把风类抽象出来的接口
     3     /// </summary>
     4     interface Subject
     5     {
     6         void Attach(Observer ob);
     7         void Detach(Observer ob);
     8 
     9         string SecretoryAction
    10         {
    11             get;
    12             set;
    13         }
    14     }

    具体的把风同学的类可继承这个接口

     1     /// <summary>
     2     /// 把风同学类
     3     /// </summary>
     4     public class Secretary : Subject
     5     {
     6         private IList<Observer> obs = new List<Observer>();
     7         private string action;
     8         public void Attach(Observer ob)
     9         {
    10             obs.Add(ob);
    11         }
    12 
    13         public void Detach(Observer ob)
    14         {
    15             obs.Remove(ob);
    16         }
    17 
    18         public void Notify()
    19         {
    20             foreach (var o in obs)
    21             {
    22                 o.Update();
    23             }
    24         }
    25         public string SecretoryAction
    26         {
    27             get { return action; }
    28             set { action = value; }
    29         }
    30     }

    客户端:

     1         public static void Main()
     2         {
     3             //把风的
     4             Secretary s = new Secretary();
     5             //玩耍小王同学
     6             Observer ob1 = new Observer1("小王", s);
     7             //玩耍小李同学
     8             Observer ob2 = new Observer1("小李", s);
     9             //玩耍小李同学
    10             Observer ob3 = new Observer2("小张", s);
    11             //把风的记下三位同学
    12             s.Attach(ob1);
    13             s.Attach(ob2);
    14             s.Attach(ob3);
    15             //发现老师来了
    16             s.SecretoryAction = "老师回来了!";
    17             //通知三位同学
    18             s.Notify();
    19             Console.ReadKey();
    20         }

    ok,观察者模式就讲完了,下面我们来总结一下:

    观察者模式:又叫 发布-订阅模式,他定义了一种一对多的依赖关系,让多个观察者对象共同监听同一个主题对象,当主题对象状态发生变化时,会通知所有观察者对象,使他们能够自动更新自己。

    观察者模式所做的事情就是解耦,让耦合的双方都依赖于抽象,而不依赖于具体,从而使得自己的变化不会影响到另一边。

    好了,观察者模式我么你就说到这里了,下一篇博文,将会讲 抽象工厂模式


    本系列将持续更新,喜欢的小伙伴可以点一下关注和推荐,谢谢大家的支持。

  • 相关阅读:
    IIS6.0PUT漏洞的利用
    练习1--利用python获取百度前3页搜索结果(可更改页数)
    笔记整理6——用python实现IP流量分析
    Django ORM 那些相关操作
    Django 中得ORM介绍和字段及字段参数
    Django 的 路由系统
    Django
    Django 的 之 视图
    Django 框架
    Django 中ORM 的使用
  • 原文地址:https://www.cnblogs.com/xiaomowang/p/6340367.html
Copyright © 2020-2023  润新知