zoukankan      html  css  js  c++  java
  • 策略模式设计的报警服务

      每当听到设计模式这个名词时,都觉得离着自己好远,有种遥不可及的感觉。当有一天,我在公交车上看到策略模式的时候,瞬间就想到原来,我在工作中已经用到过了设计模式,只是不自知而已。下面,我把我用策略模式写的一个报警服务归纳总结一下,希望能够给还在迷茫中的小程序猿们一点点启发,嘻嘻。

      我介绍一下我这个小服务的功能:这个服务就是能够实现多通路报警的服务,比如邮件报警、客户端报警、短信报警等,该服务灵活性还不错,比较方便扩展。具体如何报警我就不在这说啦,有兴趣的同学可以自己研究,我着重说一下策略模式。首先需要定义一个接口,该接口用来统一报警方法,代码如下:

    /// <summary>
    /// 报警接口,统一各种报警方式发出报警的方法
    /// </summary>
    public interface IAlarm
    {
      void Alarm(Message message);
    }

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

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

    /// <summary>
    /// 邮件报警
    /// </summary>
    public class EmailAlarm : IAlarm
    {
      /// <summary> /// 发送邮件实现了IAlarm接口的Alarm()方法 /// </summary> /// <param name="messag"></param> public void Alarm(Message message) {
        // 此处为邮件报警的具体实现代码 } }

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

    /// <summary>
    /// 客户端报警
    /// </summary>
    public class ClientAlarm : IAlarm
    {
         /// <summary>
         /// 实现接口IAlarm接口的Alarm()方法
         /// </summary>
         public void Alarm(Message message)
         {
             //此处为客户端实现报警的具体代码
         }
    }
                                    

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

    /// <summary>
    /// 统一发出各种报警的类,将所有调用报警的操作封装在这个类中,主程序需要报警时,直接调用这个类就可以,无需知道其他任何类的存在
    /// </summary>
    public class AlarmContext
    {
      private static readonly IDictionary<AlarmWay,IAlarm> _alarmsDic = new Dictionary<AlarmWay, IAlarm>();
      static AlarmContext()
       {
        foreach (AlarmWay way in Enum.GetValues(typeof (AlarmWay)))
           {
          try
              {
            Assembly asm = Assembly.GetExecutingAssembly();
            Object obj = asm.CreateInstance("MOPlatform.Alert." + way + "Alarm", true);
                  IAlarm alarm = obj as IAlarm;
                  _alarmsDic[way] = alarm;
              }
              catch (Exception ex)
              {
                  Logger.Error("通过反射构造报警实例时出现异常:" + ex);
              }
           }
       }
    
       /// <summary>
       /// 通过发射,调用不同的报警方式
       /// </summary>
       public void HandleMessage(Message message)
       {
           foreach (AlarmWay way in Enum.GetValues(typeof(AlarmWay)))
           {
               //遍历所有的报警方式,每一种报警方式与message.AlarmWays进行按位与运算,如果运算结果仍然为当前遍历的报警方式,则说明Message中包含这种报警方式
               if ((message.AlramWays & way) == way)
               {
                   try
                   {
                       _alarmsDic[way].Alarm(message);
                   }
                   catch (Exception ex)
                   {
                       //记录错误日志
                   }
                }
           }
       }
    }

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

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

    class Program
     {
        static void Main(string[] args)
         {
            Console.WriteLine("报警服务已启动。。。");
            //message应该是从别的程序传递过来的需要报警的消息,比如在Redis队列中获取message,具体怎么获取根据需求而定。在这里为了方便,我新生成一个对象,其实不应该这样做
            Message message = new Message();
            AlarmContext context = new AlarmContext();
            context.HandleMessage(message);
    
         }
    }    

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

    /// <summary>
    /// 报警方式
    /// </summary>
    public enum AlarmWay
    {
        Email = 1,
        Client = 2,
        ShortMessage = 4
    }

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

  • 相关阅读:
    任何抛开业务谈大数据量的sql优化都是瞎扯
    关于优化for循环的注意的事项
    sql调优《二》
    页面加载通过javascript来修改控件属性
    。net内存优化
    oracle调优使用到相关sql
    oracle插入或更新某一个指定列来执行触发器
    webpack4基础入门操作(二)(讲解下webpack的配置内容)
    webpack4基础入门操作(一)
    关于一个WCF调用的服务端和客户端的配置信息集合
  • 原文地址:https://www.cnblogs.com/fenglovewang/p/3507648.html
Copyright © 2011-2022 走看看