C#委托

来源:互联网 发布:linux显示隐藏文件 编辑:程序博客网 时间:2024/06/06 09:29

 学习是一个过程,再一次看到委托,感觉理解比曾经多了一点点,或许距离真正的理解还有很大的距离,但是距离却在缩短.

       先看一下下面一个登录的小例子

namespaceConsoleApplication1{       class User   {       public string Name          {              get;             set;         }       public string Password         {             get;             set;         }  }  class UserIdentify {      public void Login(User user)       {            if (user.Name == "Bema")          {              Show("登录成功,登录信息已经保存到数据库");           }          else          {              Show("登录失败!");           }      }         private void  Save(string message)       {           Console.WriteLine(message);      }      }}  


 

 UserIdentify类封装用户登录的逻辑,这里只有一个需求,那就是登录成功给出提示.

客户端的代码为

class Program    {        static void Main(string[] args)        {                 User user = new User { Name = "Bema", Password = "123" };         UserIdentify identify = new UserIdentify();         identify.Login(user);                   Console.ReadLine();        }    }


 

      然而这样的设计肯定是无法满足用户的需求的,用户或许希望能够将登录信息保存到文本文件,而不仅仅是数据库。如果我们仅仅修改Save方法的实现,那么用户需求再次改变时我们该如何处理呢?难道要无休止地修改Save方法吗?

既然Save方法是变化的根源,我们自然会想到将其进行封装。我们创建一个名为IStrategy 的接口。

    interface IStrategy  

    {  

     void Save(); 

 

    }

 

并创建两个实现了IStrategy 的类,DBSaveTextSave,分别用来向数据库中存入信息和向文本文件中存入信息.

    class DBSave : IStrategy {     public void Save()     {         Console.WriteLine("向数据库中插入成功");      } }   class TextSave : IStrategy  {       public void Save()      {             Console.WriteLine ("向文本文件插入成功");     }       }


 

在UserService类中添加一个IStrategy类型的属性SaveStrategy

 

   class UserService  {     public IStrategy SaveStrategy { get; set; }      public UserService()     {         SaveStrategy = new DBSave();     }       public void Login(User user)      {            if (user.Name == "Bema")          {              SaveStrategy .Save();          }          else          {              SaveStrategy .Save();          }      }       }  

 

客户端代码变为如下形式。

    class Program  {     static void Main(string[] args)     {         User user = new User { Name = "Bema", Password = "123" };         UserService service = new UserService { SaveStrategy = new TextSave() };         service.Login(user);         Console.ReadLine();     }     } 


 

在声明UserService的时候,还可以将SaveStrategy设置为TextSave。这样在UserService进行逻辑处理时,使用的SaveStrategy即为TextSave,信息将被保存到文本文件中。这里运用了一个策略模式使得代码更加的灵活.但是虽然大大的提高了灵活性,但仍然没能满足客户的需求,为什么呢?

使用委托

1.用户也许会希望另一种存储方式。当然,你可以通过在客户代码处扩展IStrategy来实现自己的日志记录方式

但这种方案是否过于复杂呢?如果用户希望再用一种存储方式,是否需要逐个创建新类呢?并且这样的实现是否与客户端的耦合过于紧密呢?并且代码过于复杂且难以重用;

2. 用户也许会希望同时使用多种方式来存储数据。比如,同时向DB2、文本文件、Excel表格和word中存储数据。你当然可以在UserService中维护一个List<ILog>,但这时UserService的职责过多,显然违反了SRP。

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

我们首先来创建一个名为Save的委托。

 

public delegate void Save(); 

然后在UserService类中添加一个Log委托类型的属性SaveDelegate。

 

class UserService  

{  

    public SaveSaveDelegate { getset; }  

 

 

    // …  

}  

在客户端,我们直接声明两个静态方法,它们没有返回值。

 static void SaveToDB()  {      Console.WriteLine("向DB中存储数据成功");  }   static void SaveToText(string message)  {       Console.WriteLine("向Text中存储数据成功");} 

 

客户端声明UserService的代码变为

 

static void Main(string[] args)  {      User user = new User { Name = "Bema", Password = "123" };      UserService service = new UserService();     service.SaveDelegate = SaveToConsole;     service.SaveDelegate += SaveToText;     service.Login(user);           Console.ReadLine();  } 


      或许上面的例子阐述委托和接口有些过于牵强,事实上有些时候的确很难选择使用接口还是委托。但所有委托适用的情况同样可以使用包含单一方法的接口来实现的。在某种程度上,可以说委托是接口(仅定义了单一方法)的一种轻量级实现,它更灵活,也更方便。

0 0
原创粉丝点击