编写一个棒球模拟系统。要达到的效果:输入棒球的轨迹和距离,输出其他对象的响应(投球手能否接到球,现场观众如何反应,裁判如何反应等。)
思路:首先得有一个Ball对象。它只负责自己是否被击中(事件发生),根本不管球出去之后,由谁来接住球。那么对于其他对象(投球手、裁判、现场观众),都希望能够订购这种特定事件(监听事件),就是说当球被击中这一事件发生之后,能得到通知,然后各自做出反应。
类似这样的例子是很多的,GOF对它进行了抽象,称为 Observer设计模式: Observer 设计模式是为了定义对象间的一种一对多的依赖关系,以便于当一个对象的状态改变时,其他依赖于它的对象会被自动告知并更新。
在创建这个事件之前,先看看我们平常用的最普通的按钮click事件完整的是怎样创建的。
一、首先在内部已经集成好的一个类里声明如下:
public event EventHandler Click;
以此来通知其他对象,存在这么一个click事件,以便其他对象来订购这个事件。
其中,public表明允许其他类中的对象访问。EventHandler是为了告诉其他对象他们的事件处理方法应该是什么样子的:应该是有两个参数:object sender, EventArgs e.
二、然后在Form1.designer.cs中声明如下:
this.playBallButton.Click += new System.EventHandler(this.playBallButton_Click);
其中,playBallButton是要触发事件的那个按钮名称。
1. this.playBallButton.Click这告诉C#将这个事件处理程序关联到playBallButton引用所指向的对象的click事件中。
2.+=操作符告诉C#为一个事件关联一个事件处理程序。
3. new System.EventHandler(this.playBallButton_Click)指定了事件处理方法名称、参数。
三、最后在Form1. cs中实现事件处理程序:
看完了click事件的完整创建过程,下面开始着手写ballInPlay的事件:
1. Form1中:
public partial class Form1 : Form
{
Ball ball = new Ball();
Pitcher pitcher;
Fan fan;
public Form1()
{
InitializeComponent();
pitcher = new Pitcher(ball);
fan = new Fan(ball);
}
private void playBallButton_Click(object sender, EventArgs e)//按钮按下进入这个方法
{
BallEventArgs ballEventArgs = new BallEventArgs(
(int)trajectory.Value, (int)distance.Value);//建立一个表示参数的对象。
ball.OnBallInPlay(ballEventArgs);//调用ball类中的OnBallInPlay方法
}
}
2.Ball这个类中:
class Ball
{
public event EventHandler<BallEventArgs> BallInPlay;//模仿click事件,用event关键字声明事件,通知其他类有这么一个BallInPlay事件。
public void OnBallInPlay(BallEventArgs e)//创建事件的一个方法。当playBallButton按钮按下去之后进入这个方法
{
EventHandler<BallEventArgs> ballInPlay = BallInPlay;//先复制给另一个变量,然后检查是否为null,再用它产生事件。
if (ballInPlay != null)
ballInPlay(this, e);//经过这一句就产生BallInPlay事件了?
}
}
3.Pitcher这个类中:
class Pitcher
{
public Pitcher(Ball ball)
{
ball.BallInPlay += ball_BallInPlay;//对象来订购事件
}
void ball_BallInPlay(object sender, EventArgs e)//事件处理
{
if (e is BallEventArgs)
{
BallEventArgs ballEventArgs = e as BallEventArgs;//向下强制转换,以便使用它的属性
if ((ballEventArgs.Distance < 95) && (ballEventArgs.Trajectory < 60))
CatchBall();
else
CoverFirstBase();
}
}
private void CatchBall()
{
Console.WriteLine("Pitcher: I caught the ball");
}
private void CoverFirstBase()
{
Console.WriteLine("Pitcher: I covered first base");
}
}
下面关键地方我们单步运行一下,看一下事件之间是怎样联系起来的。
1.运行到ballInPlay(this, e);后点击单步运行;
2.之后跳到这里:第一个订购此事件的类中:Pitcher类。
3.然后到第二个订购此事件的类中:fan类中
这样,就把各个类的事件处理程序(订购过同一事件)一个接一个地串起来关联到这个事件。
后来看到一篇讲解“事件”更加通俗易懂的文章,在下一篇《C# 中的委托和事件》中:当然,这篇文章有点长,先是讲解了委托,然后再引出事件,虽然有点长,但是细细看下来收获会很大。
本篇代码下载:
http://download.youkuaiyun.com/detail/u013480539/9668446