最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

c# 使用計時器和觀察者模式實現報警推送需求

 更新時間:2020年07月03日 10:07:44   作者:長沙大鵬  
這篇文章主要介紹了c# 使用計時器和觀察者模式實現報警推送需求,文中示例代碼非常詳細,幫助大家更好的理解和學習,感興趣的朋友可以了解下

前言

這兩天面試了一個物聯網公司高級研發(fā),面試題是下面這樣子

公司領導,部門主管,小組組長,組成員4級,假如有個 疫情預警,先通知組人員(對個人,主要有一個處理就算處理了) 如果3分鐘沒處理,就往組長發(fā)短信,如果組長3分鐘沒處理就往上級推送。一級一級的。 要求單程序并發(fā)至少支持1000tps預警事件

說實話上面需求在我做的過往項目里有過類似需求,我也只是依稀記得自己是怎么做的。類似于使用第三方任務調度框架完成上面的3分鐘超時處理,然后至于分級發(fā)送則更簡單了,再不濟就是使用if、else這樣的最原始驗證即可。但是這樣的題目丟到面試題上我是一下就不知所措了。自然最終的結果也不盡人意(我最終提交的代碼就是采用一個事件總線實現報警的推送,但是并未對其進行超時分級發(fā)送) 這個自然是錯誤的,我其實當時也想過使用Timer,但是內心對Timer就是感覺用性能做代價去換取最終的結果。

解析需求

過了幾天還是覺得要手純擼代碼將上面功能擼出來,不然如何成長呢!
拆分下需求可以得到的消息是有一個事件。這個事件就是報警事件,通過報警事件需要將消息推送給不同職位的工作人員,而且必須遵循崗位從下至上,但凡人員收到報警消息則表示報警通知已完成,其次就是有一個三分鐘需要處理。

通過上面的需求分析可以知道我們必須要定義一個枚舉,記錄職稱高低。

  /// <summary>
  /// 工作級別
  /// </summary>
  public enum JobLevel : int
  {
    公司領導 = 1,
    部門主管 = 2,
    小組組長 = 3,
    組成員 = 4
  }

其次我們至少存在兩個類,一個是產生報警的對象,這個對象有需要通知的報警信息和報警信息發(fā)送結果,當然更加少不了我們訂閱了報警消息的訂閱者。這里想了下,可以采用觀察者設計模式進行解耦。

  /// <summary>
  /// 發(fā)布者接口
  /// </summary>
  public interface IPublish
  {
    /// <summary>
    /// 新增訂閱者(觀察者)
    /// </summary>
    /// <param name="subscriber"></param>
    void AddSubscriber(SubscriberPeopleBase subscriber);
 
    /// <summary>
    /// 移除訂閱者(觀察者)
    /// </summary>
    /// <param name="subscriber"></param>
    void RemoveSubscriber(SubscriberPeopleBase subscriber);
 
    /// <summary>
    /// 發(fā)送報警消息
    /// </summary>
    void SendNotify();
  
    /// <summary>
    /// 出現警報
    /// </summary>
    /// <param name="msg">警報消息</param>
    void CreateJB(string msg);

接下來就是實現上面接口了!

/// <summary>
/// 報警發(fā)布者
/// </summary>
public class Baojing : IPublish
{
    /// <summary>
    /// 訂閱者集合
    /// </summary>
    public List<SubscriberPeopleBase> SubscriberLst { get; set; }
 
    /// <summary>
    /// 報警消息
    /// </summary>
    public string Msg { get; set; }
 
    /// <summary>
    /// 有無接收成功
    /// </summary>
    public bool IsSucess { get; set; }
 
    /// <summary>
    /// 消息通知計數器
    /// </summary>
    public Timer NotifyTimer { get; set; }
 
    /// <summary>
    /// 記錄當前發(fā)送消息的崗位
    /// </summary>
    public JobLevel CurrentJobLevel = JobLevel.組成員;
 
    public void AddSubscriber(SubscriberPeopleBase subscriber)
    {
      if (SubscriberLst == null) SubscriberLst = new List<SubscriberPeopleBase>();
      SubscriberLst.Add(subscriber);
    }
 
    public void CreateJB(string msg)
    {
      Msg = msg;
    }
 
    public void RemoveSubscriber(SubscriberPeopleBase subscriber)
    {
      if (SubscriberLst != null) SubscriberLst.Remove(subscriber);
    }
 
 
    /// <summary>
    /// 發(fā)送報警消息
    /// </summary>
    public void SendNotify()
    {
      if (SubscriberLst?.Count > 0)
      {
        //循環(huán)從職位低到高
        SubscriberLst.OrderByDescending(p => (int)p.Title);  
         //立即執(zhí)行CheckNotifySendResult,以為3秒為間隔
        NotifyTimer = new Timer(CheckNotifySendResult, null, 0, 3000);       
      }
    }
 
    public void CheckNotifySendResult(object stat)
    {
      //先要停止定時器,防止并發(fā)
      NotifyTimer.Change(-1, 3000);
      //第一次發(fā)給職位最小 枚舉最大的組成員
      SubscriberPeopleBase subscriberPeople = SubscriberLst.Find(p =>
       (((int)CurrentJobLevel + 1) - (int)p.Title) == 1);
      if (subscriberPeople == null) return; //已經是最小的
      if (!IsSucess)
      {
        IsSucess = subscriberPeople.ReceiveData(this);
        if (!IsSucess)
        {
          CurrentJobLevel = CurrentJobLevel!= JobLevel.公司領導?(JobLevel)((int)CurrentJobLevel) - 1: JobLevel.公司領導;
          NotifyTimer.Change(3000, 3000);
        }
      }
      else
      {
        Console.WriteLine($"停止計數器 {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
        NotifyTimer.Dispose();
      }
    }
  }

還需要有訂閱者,訂閱者使用抽象類方式降低耦合性(其實還是要用事件總線,將耦合性和擴展性提高一個檔次)

 /// <summary>
  /// 訂閱者
  /// 其實這里還不夠完善,理論上后續(xù)如果每個職位的訂閱者對報警消息的處理不同則在下面的接收消息里會存在一些冗余代碼,
  /// 理想情況是不同級別應該有不同的實現,這樣可以足夠抽象,后續(xù)擴展也更加方便
  /// </summary>
  public abstract class SubscriberPeopleBase
  {
    /// <summary>
    /// 工作職位(級別)
    /// </summary>
    public JobLevel Title { get; set; }
 
    public SubscriberPeopleBase(JobLevel title)
    {
      Title = title;
    }
 
    public virtual bool ReceiveData(Baojing baojing)
    {
      if (Title == JobLevel.公司領導)
      {
        Console.WriteLine($"出現報警信息:{baojing.Msg},當前訂閱者:{Title.ToString()} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
        return true;
      }
      else
      {
        Console.WriteLine($"出現報警信息:{baojing.Msg},當前訂閱者:{Title.ToString()},默認未應答 {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
        return false;
      }
    }
  }

再加個子類,重寫下接收警報的方法

public class SubscriberPeople : SubscriberPeopleBase
 {
    public SubscriberPeople(JobLevel title) : base(title) { }
    public override bool ReceiveData(Baojing baojing)
    {     
      if (Title == JobLevel.公司領導)
      {
        Console.WriteLine($"出現最新報警信息:{baojing.Msg},當前訂閱者:{Title.ToString()} 已成功應答 {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
        return true;
      }
      else
      {
        Console.WriteLine($"出現報警信息:{baojing.Msg},當前訂閱者:{Title.ToString()},默認未應答 {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
        return false;
      }
    }
 }

最終我的main方法是這樣

 static void Main(string[] args)
 {
      IPublish publish = new Baojing();
      publish.AddSubscriber(new SubscriberPeople(JobLevel.組成員));
      publish.AddSubscriber(new SubscriberPeople(JobLevel.公司領導));
      publish.AddSubscriber(new SubscriberPeople(JobLevel.部門主管));
      publish.AddSubscriber(new SubscriberPeople(JobLevel.小組組長));
      publish.CreateJB("主機溫度過高!");
      publish.SendNotify();
      Console.ReadLine();
  }

調試的效果如下:

明天還是完善下,將使用EventBus,將耦合性再度降低,同時也能讓接收方法更加靈活性,能實現不同級別的職員做出不同的響應!

以上就是c# 使用計時器和觀察者模式實現報警推送需求的詳細內容,更多關于c# 實現報警推送需求的資料請關注腳本之家其它相關文章!

相關文章

  • 詳解C# WinForm如何實現自動更新程序

    詳解C# WinForm如何實現自動更新程序

    在C/S這種模式中,自動更新程序就顯得尤為重要,它不像B/S模式,直接發(fā)布到服務器上,瀏覽器點個刷新就可以了。本文就為大家準備了WinForm實現自動更新程序的示例代碼,需要的可以參考一下
    2022-10-10
  • C#實現語音視頻錄制-附demo源碼

    C#實現語音視頻錄制-附demo源碼

    在很多語言視頻軟件系統(tǒng)中,經常有將實時的音頻或者是視頻錄制為文件保存到磁盤空間的需求,本篇給大家講C#實現語音視頻錄制-附demo源碼,感興趣的朋友一起來學習吧
    2015-08-08
  • .Net多進程通信共享內存映射文件Memory?Mapped

    .Net多進程通信共享內存映射文件Memory?Mapped

    這篇文章主要介紹了.Net多進程通信共享內存映射文件Memory?Mapped的使用示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-04-04
  • C#中序列化實現深拷貝,實現DataGridView初始化刷新的方法

    C#中序列化實現深拷貝,實現DataGridView初始化刷新的方法

    下面小編就為大家?guī)硪黄狢#中序列化實現深拷貝,實現DataGridView初始化刷新的方法。小編覺得挺不錯的,現在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-02-02
  • C# 異步返回類型的幾種方式

    C# 異步返回類型的幾種方式

    異步編程已經成為一種重要的編程范式,本文主要介紹了C#異步返回類型的幾種方式,文中通過示例代碼介紹的非常詳細,需要的朋友們下面隨著小編來一起學習學習吧
    2024-03-03
  • Unity實現移動物體到鼠標點擊位置

    Unity實現移動物體到鼠標點擊位置

    這篇文章主要為大家詳細介紹了Unity實現移動物體到鼠標點擊位置,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-08-08
  • C# 清除cookies的代碼

    C# 清除cookies的代碼

    不同的瀏覽器會把cookie文件保存在不同的地方.這篇文章主要介紹了C# 清除cookies的代碼,需要的朋友可以參考下
    2016-10-10
  • C#中Random.Next方法的使用小結

    C#中Random.Next方法的使用小結

    在C#中,Random.Next()方法用于生成一個隨機整數,本文主要介紹了C#中Random.Next方法的使用小結,具有一定的參考價值,感興趣的可以了解一下
    2024-01-01
  • C#前端驗證和后臺驗證代碼實例

    C#前端驗證和后臺驗證代碼實例

    這篇文章主要介紹了C#前端驗證和后臺驗證代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-07-07
  • unity使用射線實現貼花系統(tǒng)

    unity使用射線實現貼花系統(tǒng)

    這篇文章主要為大家詳細介紹了unity使用射線實現貼花系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-07-07

最新評論

木兰县| 准格尔旗| 东至县| 威远县| 灵璧县| 新宁县| 中超| 新泰市| 阜新| 嘉荫县| 射阳县| 漠河县| 和政县| 大安市| 石林| 华亭县| 鸡泽县| 中宁县| 漾濞| 昌江| 甘孜| 罗山县| 苗栗市| 宜都市| 平湖市| 抚松县| 新龙县| 阿尔山市| 都江堰市| 芜湖市| 阜城县| 延长县| 上虞市| 兴文县| 如东县| 彭州市| 甘德县| 沛县| 蕉岭县| 浙江省| 建瓯市|