分享我所理解的c#中的委托『原创』

keyake863 2008-05-23 11:05:39
c#语言的一大特点就是 高聚合,低耦合。而委托也很明显的体现了这样的一个特征。委托的价值并不在于它能帮你解决什么难题,而在于它能帮助你优化你的程序。

很多情况下不用委托我们也能完成工作,也许偶尔会觉得使用委托更加麻烦,但是正如前面所说委托能使代码更加的低耦合,更加具有可读性,更加容易根据需求的改变而改变,也更加的简少了代码量。

既然有那么多优点我们当然要使用,如果你对委托的优点仍然有所怀疑,那么我们一起完成下面的例子。

有一个运动员,他叫green,他每周要训练三天,周一,周二和周三。而他每天训练完成后都要做不同的事情,但是这些事情是有规律的,他周一要将训练的分数交给manager,周二不用交了,但是他要自己记录下这个分数,周三他不用交也不用记录,但是他要把他的分数给他的队友看。

这样一个游戏规则,我们试着用代码来实现它,首先,我们不考虑委托。

显然,这个过程需要运动员在每次完成训练后传递一些信息(参数)给某些方法(提交给manager的方法,记录的方法,传递给其他队友的方法)我们把这三个方法写在一个DoSomeThing类中,result是我们定义的一个string用来记录结果。

public class DoSomeThing
...{
public void GiveCodeToManager(object sender, CustomeEvetnArgs e)
...{
result +=sender.ToString()+ "已经将分数:" + e.Code.ToString() + "送给Manager";
}
public void RecodeCode(object sender, CustomeEvetnArgs e)
...{
result += sender.ToString() + "已经将分数:" + e.Code.ToString() + "记录";
}
public void GiveCodeToOthers(object sender, CustomeEvetnArgs e)
...{
result += sender.ToString() + "已经将分数:" + e.Code.ToString() + "给其他人";
}
}
传递的参数中有一个CustomeEvetnArgs,这是我们自定义的传递信息类。这个类将包含传递的分数,如下

public class CustomeEvetnArgs : EventArgs
...{
private string _code;
public string Code
...{
get ...{ return _code; }
set ...{ _code = value; }
}
}
我们还要有一个player类,运动员类,这个类中要根据时间的不同来调用dosomething类中的方法,并传递参数

public class player
...{
private string _code;
public string Code
...{
get ...{ return _code; }
set ...{ _code = value; }
}

private string _thedate;
public string TheDate
...{
get ...{ return _thedate; }
set ...{ _thedate = value; }
}

public void OnComplete()
...{
CustomeEvetnArgs e = new CustomeEvetnArgs();
e.Code = this.Code;

DoSomeThing things = new DoSomeThing();
if (_thedate == "Mon")
...{ things.GiveCodeToManager(this, e); }
if (_thedate == "Tues")
...{ things.RecodeCode(this, e); }
if (_thedate == "Wed")
...{ things.GiveCodeToOthers(this, e); }
}
}
这样基本类型就完成了,我们现在来调用它们

player green = new player();
green.Code = "A+";
green.TheDate = "Tues";
green.OnComplete();
Response.Write(result);
嗨,我们实现了这个游戏。测试一下,确实没有问题,如果你是一个细心的人也许你会回过头来检查你的代码,是否会发现一些不尽人意的地方?你会发现运动员类中包含的东西太多了,比如日期并不是一个运动员的属性,运动员和日期有什么关系呢?而运动员的唯一事件就是完成训练,他不需要去管其他事情了,他训练完了太累了,还要去送分数和记录成绩?也许他应该有个助手去做这些事情,所以在运动员类中并不应该出现那些if,他们使代码的耦合度太高了,当一个运动员想要改变他的训练流程时,他不得不改变player类。于是,委托出场了。

定义一个委托,使用delegate关键字,后面跟上他的参数,这个委托是要委托他去处理dosomething中的方法的,所以委托和这些方法的签名要一致。

public delegate void MyDelegate(object sender, CustomeEvetnArgs e);
于是有了这个助手,green轻松多了,他终于不用管今天是星期几了,我们重新改一下player类,这个类中去掉了thedate属性,也没有了if,只有一个委托oncomplete事件在运动员OnComplete时触发

public class player
...{
private string _code;
public string Code
...{
get ...{ return _code; }
set ...{ _code = value; }
}
public event MyDelegate oncomplete;
public void OnComplete()
...{
CustomeEvetnArgs e = new CustomeEvetnArgs();
e.Code = this.Code;
if (oncomplete != null)
...{ oncomplete(this, e); }
}
}
而这个助手要看今天是星期几,然后执行相应的方法,date是今天的日期。

DoSomeThing things = new DoSomeThing();
if (date == "Mon")
...{ green.oncomplete += new MyDelegate(things.GiveCodeToManager); }
if (date == "Tues")
...{ green.oncomplete += new MyDelegate(things.RecodeCode); }
if (date == "Wed")
...{ green.oncomplete += new MyDelegate(things.GiveCodeToOthers); }
green.OnComplete();
Response.Write(result);
这样万一游戏流程有了改变,那也跟green无关了,他只要专心训练,其他的由这个助手进行改动。

委托可以通过+= ,-=来增加和消除他在星期几所委托的方法。

高聚合 低耦合,是委托的一个很重要的用途。

大家也可以点击我的博客(点我的头像)查看,有兴趣的可以一起讨论
...全文
725 74 打赏 收藏 转发到动态 举报
写回复
用AI写文章
74 条回复
切换为时间正序
请发表友善的回复…
发表回复
大自然D使者 2008-06-16
  • 打赏
  • 举报
回复
学习了
hubblebubblepig 2008-06-16
  • 打赏
  • 举报
回复
支持!~
sssjjjpppsjp 2008-06-16
  • 打赏
  • 举报
回复
来学习的
waitinglines 2008-06-16
  • 打赏
  • 举报
回复
mark下!回头仔细看!
woshigefantong 2008-06-13
  • 打赏
  • 举报
回复
不错,能看到点有趣的东西
yaazz 2008-06-13
  • 打赏
  • 举报
回复
Mark
cylot 2008-06-13
  • 打赏
  • 举报
回复
先踩一脚!
编程有钱人了 2008-06-13
  • 打赏
  • 举报
回复
委托不是问题,问题是用委托的人!
mashifei 2008-06-13
  • 打赏
  • 举报
回复
looklook
liwei81888 2008-06-13
  • 打赏
  • 举报
回复
学习了!!
belldandy11 2008-06-13
  • 打赏
  • 举报
回复
mark
yagebu1983 2008-06-13
  • 打赏
  • 举报
回复
学习了!!
帮你顶!!!
cheng_feng001 2008-06-13
  • 打赏
  • 举报
回复
mark
devilsu 2008-05-27
  • 打赏
  • 举报
回复
我顶!先
wenkekenihao 2008-05-26
  • 打赏
  • 举报
回复
个人觉得,委托只是一个代理.举个例子我要去买一包烟,我自己也可以去.也可以叫别人去买.
叫别人去买,其实就是在使用委托.
呵呵.
alps1624 2008-05-26
  • 打赏
  • 举报
回复
学习中
零下11度 2008-05-26
  • 打赏
  • 举报
回复
委托 很好很强大。
boyle0630 2008-05-26
  • 打赏
  • 举报
回复
已前对它是一知半解,在程式中尽量不用,学习,待会来看
LutzMark 2008-05-26
  • 打赏
  • 举报
回复
通过楼主的精彩例子,我们看到了委托为我们提供了这样一种机制:把不属于该类应该背负的属性或方法(楼主例子中player类的TheDate属性)转移,取而代之的是委托实例, 把业务逻辑与方法调用的耦合延迟到客户端。
或者这样说:通过运行时绑定对象内部的委托对象(事件)即方法的调用,我们可以实现优雅的高内聚、低耦合的程序。
Luoable 2008-05-26
  • 打赏
  • 举报
回复
如果结合观察者模式一起讲讲. 就更好了.. 拓展一下..可能包含的东西更多..

飘过...
加载更多回复(54)

62,071

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

试试用AI创作助手写篇文章吧