zl程序教程

您现在的位置是:首页 >  其他

当前栏目

使用策略模式实现报警服务示例详解(短信报警)

服务模式 实现 使用 详解 示例 策略 短信
2023-06-13 09:15:15 时间

着重说一下策略模式。首先需要定义一个接口,该接口用来统一报警方法,代码如下:

复制代码代码如下:


///<summary>
///报警接口,统一各种报警方式发出报警的方法
///</summary>
publicinterfaceIAlarm
{
  voidAlarm(Messagemessage);
}

大家伙看到Message会不会比较疑惑呢,别着急,Message就是我自己定义的一个报警的模型,比如报警标题,收件人(报警报给谁呢),报警方式(邮件、客户端等)等。

定义好接口之后,我们就要实现这个接口,实现这个接口的就是各种报警方式的类,比如EmailAlarm.cs和ClientAlarm.cs,下面是邮件报警的具体实现,EmailAlarm.cs的代码(需要实现IAlarm接口的Alarm方法):

复制代码代码如下:


///<summary>
///邮件报警
///</summary>
publicclassEmailAlarm:IAlarm
{
  ///<summary>
  ///发送邮件实现了IAlarm接口的Alarm()方法
  ///</summary>
  ///<paramname="messag"></param>
  publicvoidAlarm(Messagemessage)
  {
    //此处为邮件报警的具体实现代码
  }
}

下面是客户端报警的具体实现,ClientAlarm.cs(同样需要实现IAlarm接口的Alarm()方法)

复制代码代码如下:
///<summary>
///客户端报警
///</summary>
publicclassClientAlarm:IAlarm
{
    ///<summary>
    ///实现接口IAlarm接口的Alarm()方法
    ///</summary>
    publicvoidAlarm(Messagemessage)
    {
        //此处为客户端实现报警的具体代码
    }
}

好了,基础工作都做完,接下来我们面临的问题是我们该如何调用不同的报警实现呢?当然,在我们的报警模型Message中有报警方式这一字段,我们需要根据报警方式这个字段来发不同的报警。这个还不简单,我们根据不同的报警方式生成不同的对象,然后各自调用Alarm()方法就ok。当然,这是一种解决方法,但是这是最好的解决方法吗?ofcoursenot!听说过反射吗,小伙伴们?接下来,我将介绍如何利用反射来调用不同的报警方式:

复制代码代码如下:
///<summary>
///统一发出各种报警的类,将所有调用报警的操作封装在这个类中,主程序需要报警时,直接调用这个类就可以,无需知道其他任何类的存在
///</summary>
publicclassAlarmContext
{
  privatestaticreadonlyIDictionary<AlarmWay,IAlarm>_alarmsDic=newDictionary<AlarmWay,IAlarm>();
  staticAlarmContext()
  {
    foreach(AlarmWaywayinEnum.GetValues(typeof(AlarmWay)))
      {
      try
         {
        Assemblyasm=Assembly.GetExecutingAssembly();
        Objectobj=asm.CreateInstance("MOPlatform.Alert."+way+"Alarm",true);
             IAlarmalarm=objasIAlarm;
             _alarmsDic[way]=alarm;
         }
         catch(Exceptionex)
         {
             Logger.Error("通过反射构造报警实例时出现异常:"+ex);
         }
      }
  }

  ///<summary>
  ///通过发射,调用不同的报警方式
  ///</summary>
  publicvoidHandleMessage(Messagemessage)
  {
      foreach(AlarmWaywayinEnum.GetValues(typeof(AlarmWay)))
      {
          //遍历所有的报警方式,每一种报警方式与message.AlarmWays进行按位与运算,如果运算结果仍然为当前遍历的报警方式,则说明Message中包含这种报警方式
          if((message.AlramWays&way)==way)
          {
              try
              {
                  _alarmsDic[way].Alarm(message);
              }
              catch(Exceptionex)
              {
                  //记录错误日志
              }
           }
      }
  }
}

看到AlarmWay是不是又混乱了呢?千万别乱,AlarmWay就是我定义的一个枚举类型,里面包含了各种报警方式,具体的代码我会在文章的最后贴出。我们现在还是着重讨论上面的代码,亲爱的小伙伴们,看到上面的静态构造函数了吗?知道为什么要这样写吗?我们在静态构造函数中利用反射将枚举中所有的报警对象保存在IDictionary中,具体的保存如_alarmsDic["Email"]=(IAlarm)EmailAlarm。这样做的好处小伙伴们自己琢磨吧,嘻嘻。

最后就是我们在主程序中调用AlarmContext来发出报警,具体的调用代码如下:

复制代码代码如下:
classProgram
 {
   staticvoidMain(string[]args)
    {
       Console.WriteLine("报警服务已启动。。。");
       //message应该是从别的程序传递过来的需要报警的消息,比如在Redis队列中获取message,具体怎么获取根据需求而定。在这里为了方便,我新生成一个对象,其实不应该这样做
       Messagemessage=newMessage();
       AlarmContextcontext=newAlarmContext();
       context.HandleMessage(message);

    }
}

OK,到此为止,利用策略模式设计的报警服务就介绍完毕啦。这篇文章的主要知识点我认为有两个,一个是策略模式,另一个就是利用反射。希望广大的小伙伴们提出宝贵的意见,最后,贴出枚举AlarmWay的代码:

复制代码代码如下:
///<summary>
///报警方式
///</summary>
publicenumAlarmWay
{
   Email=1,
   Client=2,
   ShortMessage=4
}

顺便,小伙伴们思考一下为什么ShortMessage的值是4而不是3呢?