从前,在南方一块奇异的土地上,有个工人名叫彼得,他非常勤奋,对他的老板总是百依百顺。但是他的老板是个吝啬的人,从不信任别人,坚决要求随时知道彼得的工作进度,以防止他偷懒。但是彼得又不想让老板呆在他的办公室里站在背后盯着他,于是就对老板做出承诺:无论何时,只要我的工作取得了一点进展我都会及时让你知道。彼得通过周期性地使用“带类型的引用”(原文为:“typed reference” 也就是delegate??)“回调”他的老板来实现他的承诺,如下:
namespace皮特的故事_原始版
{
class Worker
{
//声明老板变量
private Boss _boss;
//通知老板
public void Advise(Boss boss)
{
//给老板变量赋值
_boss = boss;
}
//工人干活
public void DoWork()
{
Console.WriteLine("工人报告工作进度: 工作开始");
//如果老板有在,通知老板,并得到老板的反应
if (_boss != null) _boss.WorkStarted();
Console.WriteLine("工人报告工作进度: 工作进行中");
//如果老板有在,通知老板,并得到老板的反应
if (_boss != null) _boss.WorkProgressing();
Console.WriteLine("工人报告工作进度: 工作完成");
//如果老板有在,通知老板,并得到老板的评分
if (_boss != null)
{
int grade = _boss.WorkCompleted();
Console.WriteLine("工人的工作得分:" + grade+"分");
}
}
}
class Boss
{
public void WorkStarted()
{
Console.WriteLine("老板说:“好好干!”");
}
public void WorkProgressing()
{
Console.WriteLine("老板说:“没干完别来烦我!”");
}
public int WorkCompleted()
{
Console.WriteLine("老板说:“没干完别来烦我!”");
return 4;
}
}
class Universe
{
static void Main()
{
Worker peter = new Worker();
Boss boss = new Boss();
//开始通知老板,要开始干活了
peter.Advise(boss);
peter.DoWork();
Console.WriteLine("工人工作完成。");
Console.ReadLine();
}
}
}
接口
现在,彼得成了一个特殊的人,他不但能容忍吝啬的老板,而且和他周围的宇宙也有了密切的联系,以至于他认为宇宙对他的工作进度也感兴趣。不幸的是,他必须也给宇宙添加一个特殊的回调函数Advise来实现同时向他老板和宇宙报告工作进度。彼得想要把潜在的通知的列表和这些通知的实现方法分离开来,于是他决定把方法分离为一个接口:
namespace皮特的故事_接口版
{
//工人报告工作进度事件接口
interface IWorkerEvents
{
void WorkStarted();
void WorkProgressing();
int WorkCompleted();
}
class Worker
{
//声明接口类型变量指向实现接口的类
private IWorkerEvents _events;
public void Advise(IWorkerEvents events)
{
_events = events;
}
public void DoWork()
{
Console.WriteLine("工人报告工作进度: 工作开始");
//如果老板有在,通知老板,并得到老板的反应
if (_events != null) _events.WorkStarted();
Console.WriteLine("工人报告工作进度: 工作进行中");
//如果老板有在,通知老板,并得到老板的反应
if (_events != null) _events.WorkProgressing();
Console.WriteLine("工人报告工作进度: 工作完成");
//如果老板有在,通知老板,并得到老板的评分
if (_events != null)
{
int grade = _events.WorkCompleted();
Console.WriteLine("工人的工作得分:" + grade+"分");
}
}
}
//老板类实现工人报告工作进度事件接口
class Boss : IWorkerEvents
{
//老板不关心工作开始
public void WorkStarted()
{
Console.WriteLine("老板说:“没干完别来烦我!”");
}
//老板不关心工作进行情况
public void WorkProgressing()
{
Console.WriteLine("老板说:“没干完别来烦我!”");
}
//老板关心工作结果
public int WorkCompleted()
{
Console.WriteLine("老板说:“我看看结果,还不错!”");
return 4;
}
}
class Universe : IWorkerEvents
{
//宇宙关心工作开始
public void WorkStarted()
{
Console.WriteLine("宇宙说:“好,加油!”");
}
//宇宙关心工作进行情况
public void WorkProgressing()
{
Console.WriteLine("宇宙说:“干得听不错的,继续努力!”");
}
//宇宙关心工作结果
public int WorkCompleted()
{
Console.WriteLine("宇宙说:“我看看结果,还不错!”");
return 4;
}
}
class Text
{
static void Main()
{
Worker peter = new Worker();
//生成老板实例
Boss boss = new Boss();
//生成宇宙实例
Universe universe = new Universe();
//开始通知老板,要开始干活了
//一次工作的过程只能通知其中一方(老板或宇宙),无法同时通知所有实现接口的对象。
//peter.Advise(universe);
// peter.Advise(boss);
//peter.DoWork();
//这样写实际只通知了老板,没通知到宇宙
peter.Advise(universe);
peter.Advise(boss);
peter.DoWork();
//下面这样写实际上是执行了两次工作,第一次通知了宇宙,第二次通知了老板
//peter.Advise(universe);
//peter.DoWork();
//peter.Advise(boss);
//peter.DoWork();
Console.WriteLine("工人工作完成了。");
Console.ReadLine();
}
}
}