• 13委托和事件在观察者模式中的应用


    当一个被监视对象的方法执行会触发观察者Observer的方法的时候,我们就可以在被监视对象中声明委托和事件。

     

      例子

    有一个宠物追踪器挂宠物身上,只要宠物离开主人100米之外,主人手上的显示器显示警告信息并声音报警。

       1:     class Program
       2:      {
       3:          static void Main(string[] args)
       4:          {
       5:              PetTracker tracker = new PetTracker();
       6:              tracker.InstanceTrack();
       7:              Console.ReadKey();
       8:          }
       9:      }
      10:   
      11:      public class PetTracker
      12:      {
      13:          private int distance;
      14:   
      15:          //适时监控
      16:          public void InstanceTrack()
      17:          {
      18:              for (int i = 0; i < 102; i++)
      19:              {
      20:                  distance = i;
      21:                  if (distance > 100)
      22:                  {
      23:                      MakeAlert(distance);
      24:                      ShowAlert(distance);
      25:                  }
      26:              }
      27:          }
      28:   
      29:          //主人手上的追踪器终端发出警报声
      30:          private void MakeAlert(int param)
      31:          {
      32:              Console.WriteLine("嘀嘀嘀,您的宝贝已经离你" + param + "米之外了,要注意哦~~");
      33:          }
      34:   
      35:          //主人手上的追踪器终端显示报警信息
      36:          private void ShowAlert(int param)
      37:          {
      38:              Console.WriteLine("您的宝贝已经离你" + param + "米之外了,要注意哦~~");
      39:          }
      40:      }
      41:   

     

    结果:
    1

     

      定义被监视对象以及观察者Observer

    假如把以上3个方法封装到不同的类中去,那就是:

       1:     public class PetTracker
       2:      {
       3:          private int distance;
       4:   
       5:          //适时监控
       6:          public void InstanceTrack()
       7:          {
       8:              for (int i = 0; i < 102; i++)
       9:              {
      10:                  distance = i;
      11:                  if (distance > 100)
      12:                  {
      13:   
      14:                  }
      15:              }
      16:          }      
      17:      }
      18:   
      19:      public class MakerAlertSupplier
      20:      {
      21:          //主人手上的追踪器终端发出警报声
      22:          public void MakeAlert(int param)
      23:          {
      24:              Console.WriteLine("嘀嘀嘀,您的宝贝已经离你" + param + "米之外了,要注意哦~~");
      25:          }
      26:      }
      27:   
      28:      public class ShowAlertSupplier
      29:      {
      30:          //主人手上的追踪器终端显示报警信息
      31:          public static void ShowAlert(int param)
      32:          {
      33:              Console.WriteLine("您的宝贝已经离你" + param + "米之外了,要注意哦~~");
      34:          }
      35:      }
      36:   

     

    我们需要解决的问题是:
    在PetTracker类的InstanceTrack()方法中,一旦distance > 100,该如何通知MakerAlertSupplier和ShowAleartSupplier呢?

     

    如何看待上面的3个类:
    ● PetTracker可以看作是被监视对象。
    ● MakerAlertSupplier和ShowAleartSupplier看作是观察者,即Observer。

     

    解决方法:
    1、考虑到Observer的方法参数都是int类型,嗯是的,不同的方法名,相同的参数列表,我们当然可以在被监视对象中定义一个委托,与observer方法有相同的参数列表。

    2、如何做到被监视对象的委托被触发从而触发Observer的方法呢?我们需要一个委托类型的事件,通过事件变量,把Observer的方法绑定到委托上。

    3、最后当被监视对象执行方法时触发委托类型的事件,从而触发Observer的方法。

     

    完整如下:

       1:      class Program
       2:      {
       3:          static void Main(string[] args)
       4:          {
       5:              PetTracker tracker = new PetTracker();
       6:              tracker.TrackEvent += (new MakerAlertSupplier()).MakeAlert;
       7:              tracker.TrackEvent += ShowAlertSupplier.ShowAlert;
       8:   
       9:              tracker.InstanceTrack();
      10:              Console.ReadKey();
      11:          }
      12:      }
      13:   
      14:      public class PetTracker
      15:      {
      16:          private int distance;
      17:   
      18:          public delegate void TrackHandler(int param); //委托
      19:          public event TrackHandler TrackEvent; //委托类型的事件
      20:   
      21:          //适时监控
      22:          public void InstanceTrack()
      23:          {
      24:              for (int i = 0; i < 102; i++)
      25:              {
      26:                  distance = i;
      27:                  if (distance > 100)
      28:                  {
      29:                      if (TrackEvent != null)
      30:                      {
      31:                          TrackEvent(distance);
      32:                      }
      33:                  }
      34:              }
      35:          }      
      36:      }
      37:   
      38:      public class MakerAlertSupplier
      39:      {
      40:          //主人手上的追踪器终端发出警报声
      41:          public void MakeAlert(int param)
      42:          {
      43:              Console.WriteLine("嘀嘀嘀,您的宝贝已经离你" + param + "米之外了,要注意哦~~");
      44:          }
      45:      }
      46:   
      47:      public class ShowAlertSupplier
      48:      {
      49:          //主人手上的追踪器终端显示报警信息
      50:          public static void ShowAlert(int param)
      51:          {
      52:              Console.WriteLine("您的宝贝已经离你" + param + "米之外了,要注意哦~~");
      53:          }
      54:      }
      55:   

     

    结果:

    1

     

    总结:
    ● 对于方法名不同,参数列表相同的多个类方法或方法,委托抽象了他们的定义。
    ● 而委托的执行和注册就交给了委托类型的事件来做。
    ● 委托是局限在被监视对象内部的,虽然声明是public,但在客户端不能给被监视对象的委托变量赋值。

     

    参考资料:
    《.NET之美》--张子阳,感谢!

  • 相关阅读:
    读《成交》有感
    【VC++学习笔记二】绘制图片的双缓冲技术
    【VC++学习笔记一】MFC操作Excel
    敏捷软件开发
    VIM常用命令
    Ubuntu下配置samba实现文件夹共享
    linux系统编程之管道(三):命令管道(FIFO)
    linux系统编程之管道(二):管道读写规则
    linux系统编程之管道(一):匿名管道(pipe)
    《Linux环境进程间通信》系列文章链接
  • 原文地址:https://www.cnblogs.com/darrenji/p/3610399.html
Copyright © 2020-2023  润新知