<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
        

      C#基礎系列——一場風花雪月的邂逅:接口和抽象類

      前言:最近一個認識的朋友準備轉行做編程,看他自己邊看視頻邊學習,挺有干勁的。那天他問我接口和抽象類這兩個東西,他說,既然它們如此相像, 我用抽象類就能解決的問題,又整個接口出來干嘛,這不是誤導初學者嗎。博主呵呵一笑,回想當初的自己,不也有此種疑惑么。。。今天打算針對他的問題,結合一個實際的使用場景來說明下抽象類和接口的異同,到底哪些情況需要用接口?又有哪些情況需要用抽象類呢?

      C#基礎系列目錄:

      一、業務場景介紹。

      博主打算使用原來在華為做外包的時候一個場景:我們針對華為里面的設備做了一個采集設備使用率的程序,設備的類型很多,各種設備的登錄和注銷方式基本相同,但是每種設備的采集的規則又不太相同。大致的場景就這樣,我們來看代碼吧。

      二、代碼示例

      根據業務場景,我們簡單搭建代碼,先來看看代碼結構圖:

      ESTM.Spider:項目的入口程序,只為測試,這里就簡單用了一個控制臺程序。

      ESTM.Spider.Huawei:華為設備采集規則,定義接口抽象實現和具體實現。

      ESTM.Utility:解決方案的工具類和接口。

      下面來看看具體的實現代碼:

      1、工具類

      namespace ESTM.Utility
      {
          public class LoginUser
          {
              public string Username { set; get; }
      
              public string Password { set; get; }
          }
      
          public class Device
          {
              public string DeviceType { set; get; }
      
              public int WaitSecond { set; get; }
          }
      }

      2、接口設計:ISpider.cs

      namespace ESTM.Utility
      {
          //采集接口,定義采集的規則
          public interface ISpider
          {
              bool Login(LoginUser oLoginUser);
      
              string Spider(Device oDevice);
      
              void LoginOut();
          }
      }

      3、接口抽象實現類:SpiderBase.cs

         /// <summary>
          /// 公共的采集基類
          /// </summary>
          public abstract class SpiderBase : ISpider
          {
              //華為設備統一采用Telnet方式登錄。統一用戶名密碼都是admin。
              public virtual bool Login(LoginUser oLoginUser)
              {
                  Console.WriteLine("華為設備采用Telnet方式登錄。");
      
                  var bRes = false;
                  if (oLoginUser.Username == "admin" && oLoginUser.Password == "admin")
                  {
                      Console.WriteLine("用戶名密碼校驗正確,登錄成功");
                      bRes = true;
                  }
                  else
                  {
                      Console.WriteLine("用戶名密碼校驗錯誤,登錄失敗");
                  }
                  return bRes;
                 
              }
      
      
              //采集操作和具體的設備類型相關,這里用抽象方法,要求子類必須重寫
              public abstract string Spider(Device oDevice);
              
      
              //華為設備統一注銷
              public virtual void LoginOut()
              {
                  Console.WriteLine("華為設備采用Telnet方式注銷");
              }
          }

      4、接口具體實現類

        [Export("MML", typeof(ISpider))]
          public class SpiderMML:SpiderBase
          {
              //MML設備采集
              public override string Spider(Device oDevice)
              {
                  Console.WriteLine("MML設備開始采集");
                  return "MML";
              }
          }
          [Export("TL2", typeof(ISpider))]
          public class SpiderTL2:SpiderBase
          {
              //TL2設備采集
              public override string Spider(Device oDevice)
              {
                  Console.WriteLine("TL2設備開始采集");
                  return "TL2";
              }
          }

      5、在控制臺調用

        class Program
          {
              [Import("MML", typeof(ISpider))]
              public ISpider spider { set; get; }
      
              static void Main(string[] args)
              {
                  var oProgram = new Program();
                  RegisterMEF(oProgram);
      
                  oProgram.spider.Login(new LoginUser() { Username = "admin", Password = "admin" });
                  oProgram.spider.Spider(new Device() { DeviceType = "HuaweiDevice", WaitSecond = 100 });
                  oProgram.spider.LoginOut();
              }
      
              #region 注冊MEF
              private static void RegisterMEF(object obj)
              {
                  AggregateCatalog aggregateCatalog = new AggregateCatalog();
                  var thisAssembly = new DirectoryCatalog(AppDomain.CurrentDomain.BaseDirectory, "*.dll");
                  aggregateCatalog.Catalogs.Add(thisAssembly);
                  var _container = new CompositionContainer(aggregateCatalog, true);
                  _container.ComposeParts(obj);
              } 
              #endregion
          }

      6、說明

      這是一種比較典型的應用場景。接口定義規則,抽象類定義公共實現或者抽象方法,具體子類實現或者重寫抽象類方法。我們重點來看這里的中間橋梁——抽象類。我們知道,抽象類里面既可以有實現的方法,也可以有未實現的抽象方法。

      (1)在這里,Login、LoginOut方法由于子類是通用的具有相同邏輯的方法,所以我們需要在抽象類里面去實現這兩個方法,如果子類沒有特殊需求,調用的時候直接用父類的方法就好了; 如果子類有特殊需求,可以override父類的方法。這樣設計既提高了代碼的復用率,也可以靈活復寫。

      (2)另一方面,抽象類里面也定義了抽象方法,這個抽象方法在這里的作用就很好體現了:如果子類不重寫父類的抽象方法,編譯通不過,直接報錯。這樣就要求我們子類必須要重寫抽象方法。從這點來說,抽象方法和接口的方法申明區別不大。

      (3)如果這里不用抽象類,就用一個普通的類來代替行不行?博主的答案是:行!但不好!如果你非要說,我用一個普通的類,將public abstract string Spider(Device oDevice);這個方法寫成

      public virtual string Spider(Device oDevice)
      {
            return "";  
      }

      貌似也沒問題,反正子類要重寫的。確實,這樣設計沒問題,但是如果你不慎子類忘了override呢?程序還是會跑起來,運行的時候可能會報錯。微軟既然給我們提供了abstract這么一個東西,我們為什么不用呢。

      三、代碼擴展

      以上我們抽象類使用的必要性和使用方法是介紹完了。那么接下來新的問題來了,可能就有人問了,你上面說了叭叭叭說了這么多,無非就是說了抽象類的必要性,那么既然抽象類這么有用,我們直接用抽象類就好了,你干嘛還要弄一個接口呢。談到這里,就要說到面向接口編程。其實,面向接口編程和面向對象編程并不是平級的,它并不是比面向對象編程更先進的一種獨立的編程思想,而是附屬于面向對象思想體系,屬于其一部分。或者說,它是面向對象編程體系中的思想精髓之一。而之前博主的文章就分享過面向接口編程的意義所在:依賴倒置,松耦合。那么這里是否可以不要接口,直接用抽象類代替呢?答案還是行!但不好!

      比如我們現在又來了新的需求,中興也要用我們的采集系統,但是它的設備類型、登錄注銷方式和華為設備區別非常大。那么這個時候我們接口的意義就體現了,如果我們使用接口,我們只需要再重寫一個ESTM.Spider.Huawei這個項目就好了,我們暫且命名叫ESTM.Spider.Zhongxing。我們來看看:

      代碼如下:

      namespace ESTM.Spider.Zhongxing
      {
          /// <summary>
          /// 中興設備采集基類
          /// </summary>
          public abstract class SpiderBase:ISpider
          {
              //中興設備通用登錄方法
              public virtual bool Login(LoginUser oLoginUser)
              {
                  Console.WriteLine("中興設備登錄前多了一個數據校驗:.......");
                  Console.WriteLine("中興設備采用WMI方式登錄。");
      
                  var bRes = false;
                  if (oLoginUser.Username == "root" && oLoginUser.Password == "root")
                  {
                      Console.WriteLine("用戶名密碼校驗正確,登錄成功");
                      bRes = true;
                  }
                  else
                  {
                      Console.WriteLine("用戶名密碼校驗錯誤,登錄失敗");
                  }
                  return bRes;
              }
      
              //定義抽象方法,要求子類必須重寫
              public abstract string Spider(Device oDevice);
      
              //中興設備通用注銷
              public virtual void LoginOut()
              {
                  Console.WriteLine("中興設備采用WMI方式注銷");
              }
          }
      }
      namespace ESTM.Spider.Zhongxing
      {
          [Export("ZXGC", typeof(ISpider))]
          public class SpiderZXGC:SpiderBase
          {
              public override string Spider(Utility.Device oDevice)
              {
                  Console.WriteLine("中興ZXGC設備開始采集");
                  return "ZXGC";
              }
          }
      }
      namespace ESTM.Spider.Zhongxing
      {
          [Export("ZXGY", typeof(ISpider))]
          public class SpiderZXGY:SpiderBase
          {
              public override string Spider(Utility.Device oDevice)
              {
                  Console.WriteLine("中興ZXGY設備開始采集");
                  return "ZXGY";
              }
          }
      }

      由于這里采用了接口,我們將ESTM.Spider.Zhongxing這個項目開發完成后生成dll,將dll放到控制臺程序中,直接通過MEF導入不同的子類對象就可以使用,不需要更改控制臺里面的大部分東西。如果不用接口,而是直接用抽象類代替,那么控制臺里面大部分的代碼都得改,并且控制臺程序依賴多個dll,對設計的松耦合也不利。博主這里為了簡單,用了MEF來簡單導入,其實正式項目中,應該是用工廠采用反射直接創建出具體的實例。

      四、總結

      1、接口是一組規則的集合,它主要定義的是事物的規則,體現了是這種類型,你就必須有這些規則的概念。它的目的主要是依賴倒置和松耦合,從這點來說,接口不能省掉或者用抽象類代替。總而言之,接口和抽象類不可同日而語。

      2、抽象類主要用于公共實現和約束子類必須重寫。以上面的例子說明,Login、Loginout用于公共實現,提高了代碼復用,Spider用于抽象,約束子類必須要重寫Spider方法。這也就是這里不能用普通類的原因。

      3、用一句話概括接口和抽象類的區別:使用抽象類是為了代碼的復用,而使用接口的動機是為了實現多態性(依賴倒置)。至于使用的時候到底是用接口還是抽象類,看具體的情況。

       

      posted @ 2015-11-10 17:00  懶得安分  閱讀(3775)  評論(6)    收藏  舉報
      主站蜘蛛池模板: 色老99久久九九爱精品| 中文字幕无码av不卡一区| 日本内射精品一区二区视频| 亚洲老熟女一区二区三区| 四虎av永久在线精品免费观看| 九九热在线视频精品免费| 人妻少妇偷人无码视频| 亚洲色大成网站WWW永久麻豆| 人人做人人妻人人精| 美女一区二区三区亚洲麻豆| 非会员区试看120秒6次| 午夜射精日本三级| 伊人大杳焦在线| 国产成人AV男人的天堂| 亚洲日韩一区二区| av亚洲一区二区在线| 久久五月丁香激情综合| 南昌县| 亚洲春色在线视频| 一本大道久久东京热AV| 国产亚洲精品成人aa片新蒲金 | 国产极品视频一区二区三区| 一本本月无码-| 亚洲精品揄拍自拍首页一| 久久人人爽人人爽人人av| 国产在线观看91精品亚瑟| 永久免费av网站可以直接看的| 安阳市| 91精品国产色综合久久| 2022最新国产在线不卡a| 国产日韩av二区三区| 在线免费成人亚洲av| 久久精品无码av| 久热这里只有精品12| 国产精品一区二区国产主播| 国产伦码精品一区二区| 日韩av色一区二区三区| 乌克兰美女浓毛bbw| 国产精品妇女一区二区三区| 日韩人妻无码一区二区三区99 | 亚洲一区成人在线视频|