麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 學(xué)院 > 開發(fā)設(shè)計 > 正文

C#委托基礎(chǔ):談委托和接口

2019-11-17 04:08:14
字體:
供稿:網(wǎng)友
本文是博客園中近日關(guān)于C#委托的討論所衍生出來的一個系列中的第一篇,文章作者麒麟.NET對C#委托的內(nèi)涵和外延進行了討論。用麒麟.NET的話來說:“委托是.NET Framework中一個非常炫的特性,絕不會向有些評論里說的那樣,根本沒有機會接觸。恰恰相反,我們幾乎每天都會接觸委托,使用委托。”

那么,先從示例開始,了解什么是C#委托吧。

從示例開始

假設(shè)一個系統(tǒng)的用戶登錄模塊有如下所示的代碼

class User  {      public string Name { get; set; }       public string PassWord { get; set; }  }   class UserService  {      public void Register(User user)      {           if (user.Name == "Kirin")          {              Log("注冊失敗,已經(jīng)包含名為" + user.Name + "的用戶");          }          else         {              Log("注冊成功!");          }      }       PRivte void Log(string message)      {          Console.WriteLine(message);      }  }  UserService類封裝用戶登錄的邏輯,并根據(jù)不同的登錄情況向控制臺打印不同的日志內(nèi)容。當(dāng)程序關(guān)閉時,所記錄的日志自然也隨之消失。

客戶端的代碼為

class Program  {      static void Main(string[] args)      {          User user = new User { Name = "Kirin", Password = "123" };          UserService service = new UserService();          service.Register(user);          Console.ReadLine();      }  } 使用策略模式

然而這樣的設(shè)計肯定是無法滿足用戶的需求的,用戶肯定希望能夠查看以前的日志記錄,而不僅僅是程序打開以后的內(nèi)容。如果我們僅僅修改Log方法的實現(xiàn),那么用戶需求再次改變時我們該如何處理呢?難道要無休止地修改Log方法嗎?

既然日志記錄的方式是變化的根源,我們自然會想到將其進行封裝。我們創(chuàng)建一個名為ILog的接口。

interface ILog  {      void Log(string message);  }  并創(chuàng)建兩個實現(xiàn)了ILog的類,ConsoleLog和TextLog,分別用來向控制臺和文本文件輸出日志內(nèi)容。

class ConsoleLog : ILog  {      public void Log(string message)      {          Console.WriteLine(message);      }  }     class TextLog : ILog  {      public void Log(string message)      {          using (StreamWriter sw = File.AppendText("log.txt"))          {              sw.WriteLine(message);              sw.Flush();              sw.Close();          }      }  }  在UserService類中添加一個ILog類型的屬性LogStrategy。

class UserService  {      public ILog LogStrategy { get; set; }       public UserService()      {          LogStrategy = new ConsoleLog();      }       public void Register(User user)      {           if (user.Name == "Kirin")          {              LogStrategy.Log("注冊失敗,已經(jīng)包含名為" + user.Name + "的用戶");          }          else         {              LogStrategy.Log("注冊成功!");          }      }  }   客戶端代碼變?yōu)槿缦滦问健?br>
class Program  {      static void Main(string[] args)      {          User user = new User { Name = "Kirin", Password = "123" };          UserService service = new UserService { LogStrategy = new TextLog() };          service.Register(user);          Console.ReadLine();      }  } 在聲明UserService的時候,還可以將將LogStrategy設(shè)置為TextLog。這樣在UserService進行邏輯處理時,使用的LogStrategy即為TextLog,日志將輸出到文本文件中。

我們在干什么?我們在重構(gòu)。重構(gòu)的結(jié)果是什么?重構(gòu)的結(jié)果是實現(xiàn)了一個簡單的策略模式。

使用委托

然而策略模式仍然不能滿足客戶的需求,這是為什么呢?

1. 用戶也許會希望自定義Log的實現(xiàn)。當(dāng)然,你可以通過在客戶代碼處擴展ILog來實現(xiàn)自己的日志記錄方式。如

class TextBoxLog : ILog  {      private TextBox textBox;       public TextBoxLog(TextBox textBox)      {          this.textBox = textBox;          this.textBox.Multiline = true;      }       public void Log(string message)      {          textBox.AppendText(message);          textBox.AppendText(Environment.NewLine);      }  }   但這種方案是否過于復(fù)雜呢?如果用戶希望在ListView或其他控件上顯示,是否需要逐個創(chuàng)建新類呢?并且這樣的實現(xiàn)是否與客戶端的耦合過于緊密呢?比如用戶希望在ListView的各個列中顯示日志內(nèi)容、時間、來源等不同內(nèi)容,那么在ListViewLog中對ListView硬編碼是否很難重用呢?

2. 用戶也許會希望同時使用多種日志記錄方式。比如,同時向控制臺、文本文件、客戶端控件和事件查看器中輸出日志。你當(dāng)然可以在UserService中維護一個List<ILog>,但這時UserService的職責(zé)過多,顯然違反了SRP。

下面介紹本文的主角:委托。

我們首先來創(chuàng)建一個名為Log的委托,它接收一個string類型的參數(shù)。

public delegate void Log(string message); 然后在UserService類中添加一個Log委托類型的屬性LogDelegate。

class UserService  {      public Log LogDelegate { get; set; }        // …  }  在客戶端,我們直接聲明兩個靜態(tài)方法,它們都包含一個string類型的參數(shù),并且沒有返回值。

static void LogToConsole(string message)  {      Console.WriteLine(message);  }   static void LogToTextFile(string message)  {       using (StreamWriter sw = File.AppendText("log.txt"))      {          sw.WriteLine(message);          sw.Flush();          sw.Close();      }  }  客戶端聲明UserService的代碼變?yōu)?br>
static void Main(string[] args)  {      User user = new User { Name = "Kirin", Password = "123" };      UserService service = new UserService();      service.LogDelegate = LogToConsole;      service.LogDelegate += LogToTextFile;      service.Register(user);           Console.ReadLine();  } 在構(gòu)造委托時,我們還可以使用匿名方法和Lambda表達(dá)式,在老趙的文章中詳細(xì)闡述了這些寫法的演變。

對于何時使用委托,何時使用接口(即策略模式),MSDN中有明確的描述:

在以下情況下,請使用委托:

◆當(dāng)使用事件設(shè)計模式時。

◆當(dāng)封裝靜態(tài)方法可取時。

◆當(dāng)調(diào)用方不需要訪問實現(xiàn)該方法的對象中的其他屬性、方法或接口時。

◆需要方便的組合。

◆當(dāng)類可能需要該方法的多個實現(xiàn)時。

在以下情況下,請使用接口:

◆當(dāng)存在一組可能被調(diào)用的相關(guān)方法時。

◆當(dāng)類只需要方法的單個實現(xiàn)時。

◆當(dāng)使用接口的類想要將該接口強制轉(zhuǎn)換為其他接口或類類型時。

◆當(dāng)正在實現(xiàn)的方法鏈接到類的類型或標(biāo)識時:例如比較方法。

您可能覺得上面的例子闡述委托和接口有些過于牽強,事實上有些時候的確很難選擇使用接口還是委托。java中沒有委托,但所有委托適用的情況同樣可以使用包含單一方法的接口來實現(xiàn)的。在某種程度上,可以說委托是接口(僅定義了單一方法)的一種輕量級實現(xiàn),它更靈活,也更方便。

以上就是對于C#委托中一些基本概念的介紹。
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 久久中文一区 | 午夜国产精品成人 | 亚洲国产高清一区 | 亚洲情在线 | 日日爱99 | 成人一级片毛片 | 黄色的视频免费看 | 日日狠狠久久偷偷四色综合免费 | 欧美性受xxxxxx黑人xyx性爽 | a网站在线 | 久久伊人国产精品 | 久久蜜桃精品一区二区三区综合网 | 97久久人人超碰caoprom | 国产成人综合在线 | 欧美日韩大片在线观看 | 亚洲午夜久久久久 | 综合网天天色 | 在线中文字幕不卡 | 亚洲五码在线观看视频 | 亚洲视频综合网 | 桥本有菜免费av一区二区三区 | 深夜小视频在线观看 | xxxx18韩国护士hd老师 | 久久精品观看 | 国产精品亚洲一区二区三区在线观看 | 久久欧美亚洲另类专区91大神 | 久久不射电影网 | 亚洲综合视频在线播放 | 毛片视频网站在线观看 | 黄色成人av在线 | 亚洲一区二区中文字幕在线观看 | 免看黄大片aa | 国产交换3p国产精品 | 草逼一区 | 91精品国产一区二区在线观看 | 99精品国产一区二区三区 | 激情视频在线播放 | 国产精品午夜未成人免费观看 | av电影网在线观看 | 在线观看国产网站 | 福利在线免费视频 |