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之美》--张子阳,感谢!

原文地址:https://www.cnblogs.com/darrenji/p/3610399.html