委托、事件、Observer模式
委托:方法变量,简单点说就是把方法当做变量
事件:我们可以把他看做是对委托的一种封装,这种定义并不准确,便很好理解Observer模式:定义对象间的一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新(更详细的内容可以看百度百科)这里我将用一个比较直观的例子来跟大家讨论一下委托,事件和Observer模式,为了更直观我这里不再用控制台的程序,我这里用一个简单的winFrom程序
需求是这样的:我们现在在要做一个十字路口的红绿灯控制系统,这个系统一共由三部份组成,两块红绿灯牌,一个中控系统 ,要实现的效果就是,在中控台分别控制两条路上的红绿单的开关,关于介绍委托、事件和Observer模式这方面的文章太多,我这里就不多说了,其实各人有各人的理解,怎么理解我觉得都不重要,重要的是你知道什么时候该用,就像委托无论你觉得他用函数指针的概念更好理解还是觉得方法的变量听着跟明白,其实都不重要,重要的是你知道那是怎么一会事,在什么时候能用,最后能在自己的项目灵活的使用他,这才是我们的目的。这里我就直接上例子了,这是最终的效果:
在这个程序中我们要实现的就是当点击中控台的“中山路”或“环城路”那么在上面的两个窗口的灯要发生相应的变化,这就是一个简单的Observer模式,中控台就是subject(监视对像),红绿灯就是Observer(监视者),简单点说就是红绿灯两个窗口在监视中控台窗口的变化,当中控台发生变化,红绿灯也作相应的变化,下面我们就看看实现的方法和具体的代码,因为比较简单,我的说明会相对少些,大家注意看代码里的注释。
新建一个项目,里面包三个窗口,两个类库文件;frm_center为中控台程序,frm_huancheng为环城图上的红灯,frm_zhongshan为中山路上的红灯,TrafficEvent这个是委托事件类,TrafficEventArg这个是事件参数类,用于向Observer(监视者)传递所需信息 如图:
首先我们新建一个类TrafficEvent用来声明委托和事件
using System;namespace DelegaEvent.Center{ class TrafficEvent { ////// 声明委托 /// /// /// public delegate void TrafficEventHandler(Object sender, TrafficEventArgs e); ////// 声明事件 /// public event TrafficEventHandler Traffic; ////// 方法调用 /// /// public virtual void OnTraffic(Object sender, TrafficEventArgs e) { if (Traffic != null)//已注册 Traffic(sender,e);//调用所有已注册的方法 } }}
新建一个类TrafficEventArgs用于subject(监视对像)向Observer(监视者)传递信息
using System;namespace DelegaEvent.Center{ public class TrafficEventArgs : EventArgs { ////// 当前通车的路 /// public readonly string setRoad; ////// 计时器 /// public readonly int setm; public TrafficEventArgs(string setRoad,int setm) { this.setRoad = setRoad; this.setm = setm; } }}
分别在红绿灯窗口中加入setRoad方法,用于改变红绿灯的状态;窗口的设计比较简单,这里就不赘述了
using System.Windows.Forms;using System.Drawing;namespace DelegaEvent.Center{ public partial class frm_huancheng : Form { public frm_huancheng() { InitializeComponent(); } ////// 实现红绿灯变色 /// /// /// public void setRoad(object sender, TrafficEventArgs e) { string strRoad = e.setRoad; //或取参数值 FrmCenter fc = (FrmCenter)sender;//注意这里,这种方式是不是很熟悉,在实际使用中,这个是很常用的 fc.Text = "环城路"; if (strRoad == "huancheng") { this.ovalShape1.FillColor = Color.Blue; this.ovalShape2.FillColor = this.BackColor; this.ovalShape3.FillColor = this.BackColor; } else { this.ovalShape1.FillColor = this.BackColor; this.ovalShape2.FillColor = Color.Red; this.ovalShape3.FillColor = this.BackColor; } } }}
using System.Drawing;using System.Windows.Forms;namespace DelegaEvent.Center{ public partial class frm_zhongshan : Form { public frm_zhongshan() { InitializeComponent(); } ////// 实现红绿灯变色 /// /// /// public void setRoad(object sender, TrafficEventArgs e) { string strRoad = e.setRoad; if (strRoad == "zhongshan") { this.ovalShape1.FillColor = Color.Blue; this.ovalShape2.FillColor = this.BackColor; this.ovalShape3.FillColor = this.BackColor; } else { this.ovalShape1.FillColor = this.BackColor; this.ovalShape2.FillColor = Color.Red; this.ovalShape3.FillColor = this.BackColor; } } }}
在中控台窗口绑定事件,实现当点击按钮后,另外两个窗口发生相应的变化
using System;using System.Windows.Forms;namespace DelegaEvent.Center{ public partial class FrmCenter : Form { ////// 实例化两个红绿灯窗口 /// private readonly frm_huancheng frm_h = new frm_huancheng(); private readonly frm_zhongshan frm_z = new frm_zhongshan(); public FrmCenter() { InitializeComponent(); } ////// 中山路通行 /// /// /// private void ButZhongshanClick(object sender, EventArgs e) { this.setRoad("zhongshan"); } ////// 显示两条路的红绿灯窗口 /// /// /// private void FrmCenter_Load(object sender, EventArgs e) { frm_h.Show(); frm_z.Show(); } ////// 环城路通行 /// /// /// private void but_huancheng_Click(object sender, EventArgs e) { this.setRoad("huancheng"); } ////// 把红绿灯窗口的setRoad方法绑定到Traffic事件上,并执行 /// /// private void setRoad( string strRoad) { TrafficEventArgs args = new TrafficEventArgs(strRoad,100); TrafficEvent even = new TrafficEvent(); even.Traffic += frm_h.setRoad;//注册方法 even.Traffic += frm_z.setRoad;//注册方法 even.OnTraffic(this, args); //显示红绿灯,会自动调用注册过对象的方法 } }}
很简单的一个例子,希望对刚刚接触事件编程的你有一定的帮助!