中文字幕日韩一区二区_国产一区二区av_国产毛片av_久久久久国产一区_色婷婷电影_国产一区二区精品

把委托說(shuō)透(1):開(kāi)始委托之旅 委托與接口

委托,本是一個(gè)非常基礎(chǔ)的.NET概念,但前一陣子在園子里卻引起軒然大波。先是Michael Tao隨筆讓人們將委托的寫(xiě)法與茴香豆聯(lián)系到了一起,接著老趙又用一系列文章分析委托寫(xiě)法的演變,并告誡“嘲笑孔乙己的朋友們,你們?cè)谝晃侗梢?ldquo;茴”的四種寫(xiě)法的同時(shí),說(shuō)不定也失去了一個(gè)了解中國(guó)傳統(tǒng)文化的機(jī)會(huì)呢!”。

在我個(gè)人看來(lái),委托是.NET Framework中一個(gè)非常炫的特性,絕不會(huì)向有些評(píng)論里說(shuō)的那樣,根本沒(méi)有機(jī)會(huì)接觸。恰恰相反,我們幾乎每天都會(huì)接觸委托,使用委托。

其實(shí)園子里已經(jīng)有了很多關(guān)于委托的文章,比較有代表性的有:

1. C# 中的委托和事件及其續(xù)

2. C#委托,事件理解入門 (譯稿)

3. 委托揭秘

4. ……

本系列試圖從個(gè)人對(duì)于委托的理解展開(kāi),對(duì)委托的內(nèi)涵和外延均加以討論。文中有何不妥或不正確的地方,歡迎大家拍磚斧正。

好了,下面讓我從一個(gè)示例開(kāi)始,一步一步引入委托的概念。

從示例開(kāi)始

假設(shè)一個(gè)系統(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("注冊(cè)失敗,已經(jīng)包含名為" + user.Name + "的用戶");        }        else        {            Log("注冊(cè)成功!");        }    }    privte void Log(string message)    {        Console.WriteLine(message);    }}

UserService類封裝用戶登錄的邏輯,并根據(jù)不同的登錄情況向控制臺(tái)打印不同的日志內(nèi)容。當(dāng)程序關(guān)閉時(shí),所記錄的日志自然也隨之消失。

客戶端的代碼為

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è)計(jì)肯定是無(wú)法滿足用戶的需求的,用戶肯定希望能夠查看以前的日志記錄,而不僅僅是程序打開(kāi)以后的內(nèi)容。如果我們僅僅修改Log方法的實(shí)現(xiàn),那么用戶需求再次改變時(shí)我們?cè)撊绾翁幚砟兀侩y道要無(wú)休止地修改Log方法嗎?

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

interface ILog{    void Log(string message);}

并創(chuàng)建兩個(gè)實(shí)現(xiàn)了ILog的類,ConsoleLog和TextLog,分別用來(lái)向控制臺(tái)和文本文件輸出日志內(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類中添加一個(gè)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("注冊(cè)失敗,已經(jīng)包含名為" + user.Name + "的用戶");        }        else        {            LogStrategy.Log("注冊(cè)成功!");        }    }}

客戶端代碼變?yōu)槿缦滦问健?/p>

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的時(shí)候,還可以將將LogStrategy設(shè)置為TextLog。這樣在UserService進(jìn)行邏輯處理時(shí),使用的LogStrategy即為TextLog,日志將輸出到文本文件中。

我們?cè)诟墒裁矗课覀冊(cè)谥貥?gòu)。重構(gòu)的結(jié)果是什么?重構(gòu)的結(jié)果是實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的策略模式。

使用委托

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

1. 用戶也許會(huì)希望自定義Log的實(shí)現(xiàn)。當(dāng)然,你可以通過(guò)在客戶代碼處擴(kuò)展ILog來(lái)實(shí)現(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); }}

但這種方案是否過(guò)于復(fù)雜呢?如果用戶希望在ListView或其他控件上顯示,是否需要逐個(gè)創(chuàng)建新類呢?并且這樣的實(shí)現(xiàn)是否與客戶端的耦合過(guò)于緊密呢?比如用戶希望在ListView的各個(gè)列中顯示日志內(nèi)容、時(shí)間、來(lái)源等不同內(nèi)容,那么在ListViewLog中對(duì)ListView硬編碼是否很難重用呢?

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

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

我們首先來(lái)創(chuàng)建一個(gè)名為L(zhǎng)og的委托,它接收一個(gè)string類型的參數(shù)。

public delegate void Log(string message);

然后在UserService類中添加一個(gè)Log委托類型的屬性LogDelegate。

class UserService{    public Log LogDelegate { get; set; }


// …}

在客戶端,我們直接聲明兩個(gè)靜態(tài)方法,它們都包含一個(gè)string類型的參數(shù),并且沒(méi)有返回值。

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)?/p>

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)造委托時(shí),我們還可以使用匿名方法和Lambda表達(dá)式,在老趙的文章中詳細(xì)闡述了這些寫(xiě)法的演變。

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

在以下情況下,請(qǐng)使用委托:

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

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

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

    需要方便的組合。

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

在以下情況下,請(qǐng)使用接口:

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

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

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

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

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

到此為止,我們一步一步用委托重構(gòu)了最初的代碼。再接下來(lái)的隨筆中,我們將開(kāi)始更深一步的討論。

NET技術(shù)把委托說(shuō)透(1):開(kāi)始委托之旅 委托與接口,轉(zhuǎn)載需保留來(lái)源!

鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請(qǐng)第一時(shí)間聯(lián)系我們修改或刪除,多謝。

主站蜘蛛池模板: 一区二区三区精品 | 在线精品观看 | 日韩av免费在线电影 | 久久久久久久久中文字幕 | 观看av | 天天操妹子 | 91性高湖久久久久久久久_久久99 | 日韩精品在线播放 | 99亚洲精品| 亚洲精品一区二区三区中文字幕 | 巨大荫蒂视频欧美另类大 | 一区二区三区观看视频 | 久久中文字幕一区 | 国产精品久久久爽爽爽麻豆色哟哟 | 国产精品一区在线观看你懂的 | 国产aa | 久久久精彩视频 | 免费a大片| 欧美一区免费 | 久久伊人精品一区二区三区 | 午夜影院网站 | 国产性生活一级片 | 久久日韩精品 | 综合另类 | 久久综合九九 | 国产一区精品在线 | 久久久www成人免费精品 | 亚洲精品一区中文字幕乱码 | 国产精品一区二区三区在线 | 一区二区三区久久 | 日日操夜夜操视频 | 羞羞网站在线观看 | 毛片久久久 | 欧美一级免费 | 婷婷丁香综合网 | 最近日韩中文字幕 | 一区二区三区中文字幕 | 国产成人aⅴ | 国产精品高潮呻吟久久久久 | 国产午夜一级 | 99精品久久99久久久久 |