被这个问题困扰了很多天了,逻辑上讲,C#的事件和观察者模式是绝配哦。但为什么自己总是弄不清楚,不行,必须记录一下,也算是把乱七八糟的思绪整理整理。
游戏的消息机制有很多种,观察者算是最简单的吧?大体的需求就是,tmd我在这出事了,游戏中的怪物呀,NPC呀该消停的就该消停了,音乐,对说的就是你,赶紧换掉,还有GameOver的界面呢?赶紧的,轮到出场了。就这么简单一事坑死我了,于是发誓要跟它掰扯一下。于是乎定义了怪物obb,音乐occ,界面odd,然后在主程序里大叫了一声:
MainClass
class MainClass { public static void Main() { //大喊出事了,但是没人鸟 Console.WriteLine("GameOver"); //旁边打酱油的,可以无视。 Console.Read(); } }
命令提示符界面 上,悠悠的荡漾着回响
GameOver
居然没有一个鸟的。仔细一看,原来是大家都没有听见呀!怎么做才能让大家都听到呢?一个办法是互相引用。不过这样你中有我,我中有你,大家插来插去的,,真的好么?机智的我立马想到可以一起插充气娃娃呀,绿色又环保,对就这么干:
Center
//建立一个叫Center的充气娃娃 public class Center { //保证娃娃的唯一性 private static Center instance; //放入一个我要喊叫的事件 private event EventHandler GameOver; //分发给各路怪物的监听器,专门监听我喊叫事件 public void AddEventHandler(string s, EventHandler handler) { GameOver += handler; } //这是我用来放大叫声的喇叭,否则大家怎么听的到 public void PostNotification(string s) { GameOver(null, EventArgs.Empty); } //如何保证公用一个娃娃,这就是保证. public static Center GetInstance() { return instance ?? (instance = new Center()); } }
怪物obb很踊跃,一看到买了充气娃娃,立马过来抢了抢了一个监听器:AddEventHandler。保证可以听到,听到后会有反映。
obb
//一个逗哔的小怪物 public class obb { public obb() { //马上带上了监听器,专门监听我的叫喊 Center.GetInstance().AddEventHandler("GameOver", OnGameLOver); } //它的反映就是悠悠的骂一句wocao void OnGameLOver(object sender, EventArgs e) { Console.WriteLine("wocao"); } }
有了大喇叭的我再也不能那么lowB的喊了,必须撕心裂肺的叫唤
MainClass
class MainClass { public static void Main() { //一个逗哔的obb正在场景里晃悠 new obb(); //突然用了充气娃娃给我的大喇叭喊了一声 Center.GetInstance().PostNotification("GameOver"); //旁边打酱油的,可以无视。 Console.Read(); } }
命令提示符界面 上,悠悠响起了Obb的反映
wocao
同理也可以让occ,odd做出相应的反映。
结果一看到大家有了反映,突然一下把持不住了,想喊叫些别的,怎么办?继续上充气娃娃
Center
//建立一个叫Center的充气娃娃
public class Center
{
//保证娃娃的唯一性
private static Center instance;
//把要喊叫的事件连成字典,还可以通过key查询哦
public Dictionary<string, EventHandler> eventTable = new Dictionary<string, EventHandler>();
private Center()
{
//字典里两个不同的喊叫
enentTable["GameOver"] = null;
eventTable["GameStart"] = null;
}
//分发给各路怪物的监听器,专门监听我喊叫事件
public void AddEventHandler(string s, EventHandler handler)
{
eventTable[s] += handler;
}
//这是我用来放大叫声的喇叭,否则大家怎么听的到
public void PostNotification(string s)
{
eventTable[s](null, EventArgs.Empty);
}
//如何保证公用一个娃娃,这就是保证.
public static Center GetInstance()
{
return instance ?? (instance = new Center());
}
}
充气娃娃经过充分的改造,继续测试一下。
occ
//矫情的音音occ public class occ { public occ() { //傲娇的带着监听器 Center.GetInstance().AddEventHandler("GameStart", OnGameStart); } //悠悠的反映 void OnGameStart(object sender, EventArgs e) { Console.WriteLine("oh on!"); } }
MainClass
class MainClass
{
public static void Main()
{
//一个逗哔的obb正在场景里晃悠
new obb();
new occ();
//突然用了充气娃娃给我的大喇叭喊了一声
Center.GetInstance().PostNotification("GameOver");
//又情不自禁的喊了一声
Center.GetInstance().PostNotification("GameStart");
//旁边打酱油的,可以无视。
Console.Read();
}
}
命令提示符界面 上,悠悠响起了Obb,Occ的反映
wocao oh on!
这样的一个好处是,喊不喊是我的事,想喊就喊,听不听是各物件的事,想听就听。
隔壁的小明和小红一看,有这么好的一个喇叭,大家都你一下我一下的喊了起来,那么问题又来了,如何让物件对小明的喊叫其反应,对小红的不反应呢?继续改造娃娃
Center
//建立一个叫Center的充气娃娃
public class Center
{
//保证娃娃的唯一性
private static Center instance;
//把要喊叫的事件连成字典,还可以通过key查询哦
public Dictionary<string, EventHandler> eventTable = new Dictionary<string, EventHandler>();
private Center()
{
//字典里两个不同的喊叫
enentTable["GameOver"] = null;
eventTable["GameStart"] = null;
}
//分发给各路怪物的监听器,专门监听我喊叫事件
public void AddEventHandler(string s, EventHandler handler)
{
eventTable[s] += handler;
}
//这是我用来放大叫声的喇叭,否则大家怎么听的到
public void PostNotification(string s)
{
eventTable[s](null, EventArgs.Empty);
}
//加了发起者的喇叭,这下全世界都知道是谁干的了
public void PostNotification(string s,object sender)
{
eventTable[s](sender, EventArgs.Empty);
}
//如何保证公用一个娃娃,这就是保证.
public static Center GetInstance()
{
return instance ?? (instance = new Center());
}
}
obb率先发起了对小明的拥抱和对小红的拒绝,作为搞基,它的反映也有了变化:
obb
//一个逗哔的小怪物 public class obb { public obb() { //马上带上了监听器,专门监听我的叫喊 Center.GetInstance().AddEventHandler("GameOver", OnGameLOver); } //它的反映就是悠悠的骂一句wocao void OnGameLOver(object sender, EventArgs e) { if (sender!=null){ //获取发起者的名字 string temp = sender.GetType().Name; //对小明的反映 if (temp == "xiaom") Console.WriteLine("wocao "+temp); else //对其它的反映 Console.WriteLine("meikong "+temp); } } }
喊叫也有了新的规范.
Center.GetInstance().PostNotification("GameOver", this);
注释污得有趣233