一。发布者订阅者模型图解。
从图中我们看有一个部分组成?
- 发布者
- 订阅者
- 事件绑定
- 事件信息
3,4部分容易混为一谈,我们这里做一个例子用于理解:
要是实现A->B货物的运输,需要什么呢?需要一条能通的道路,还需要一辆运载了货物的车。A此时就是发布者,B是订阅者,事件绑定就是一条能通的道路,事件信息就是这个运载了货物的车。如果只有事件绑定(道路)而没有事件信息(货物车),就没有可以传输的东西了。
二。C#中委托和事件的命名规范。
- 什么是事件?和委托指针有区别吗?
我认为并没有,都可以指向多个函数。
命名语法:public event delegate 事件名; 与普通的委托指针多了个event - 委托的命名规范:委托就是为了创建事件(委托指针),因此它的名字要根据事件名来设计通常是事件名Handler
- 事件信息:这是一个不同于发布者和订阅者的类,通常他继承EventArgs。
- .net桌面应用应用中经常使用的委托就是(object sender,EventArgs e)
<1>前一个参数表示消息的发布者
<2>后一个参数表示消息的具体内容。
三。通过一个实例来解析这个模型。
-
我们将严格按照模型进行分布讲解
背景:
<1>创建一个”憨有钱“银行的一个账户对象,账户的号码是12345678910。
<2>创建一个手机对象,有手机号123456789,创建邮箱对象有邮箱号码123456789@qq.com。
<3>起初这些对象没有什么关系,但是可以通过创建对象后使用事件绑定的方法实现:在账户对象中取钱,会向这个手机和邮箱里面发送取款消息。 -
实例剖析
<1>按照上面的模型创建对象
发布者:银行账户
订阅者:手机,邮箱
事件绑定:通过银行账户对象的委托事件与手机消息,邮件消息绑定。
事件消息:每次交易时产生,银行账户发布,在各个对象之间传递
<2>通过发布者对象内部启动事件
<3>订阅者按道理应该会接收到消息
3.我们按过程写类。
<1>消息类:交易信息
public class UserEventArgs : EventArgs
//事件的信息类,这个类需要继承EnventArg并且以EnvenArg结尾
{
public readonly string amount;
public string time;
public UserEventArgs(string amount)
{
this.amount = amount;
this.time = System.DateTime.Now.ToString();//获取当前交易的事件
}
}
<2>发布者:银行账户类
//发布者,也就是被监视的对象-银行账号
class BankAccount:object
{
static public readonly string bankname = "憨有钱银行";
//本银行的名字是对所有的账户都相同的
public string accountnumber;
public BankAccount(string accountnumber)//构造函数,写入账户号码
{ this.accountnumber = accountnumber; }
public override string ToString()//重写object的ToString方法。
{ return bankname + "向账户" + accountnumber + "发出提醒:"; }
//声明一个处理银行交易的委托,委托的名字应该是 事件名handler
//委托的参数必须是有一个消息发送者,消息内容
public delegate void ProcessTranEventHandler(object sender, UserEventArgs e);
//声明一个事件
public event ProcessTranEventHandler ProcessTran;
protected virtual void OnProcessTran(UserEventArgs e)
{
if (ProcessTran != null)
{
ProcessTran(this, e);
}
}
//很多人会问,直接把事件放在Peocess函数中不就行了?不是更简单吗?
//其实这里为类的扩展做了准备,如果
<3>订阅者:手机,邮箱类
//订阅者Email
class Email
{
private string emailaddress;
public Email(string emailaddress)//构造函数初始化
{ this.emailaddress = emailaddress; }
public void SendEmail(object sender, UserEventArgs e)
{
Console.WriteLine(sender.ToString());
Console.WriteLine("向您的邮箱" + this.emailaddress + "发送邮件:");
Console.WriteLine("\t 您在" + e.time + "取款金额为" + e.amount);
}
}
//订阅者手机
class Mobile
{
public string mobilenumber;
public Mobile(string mobilenumber)
{ this.mobilenumber = mobilenumber; }
public void SendNotification(object sender, UserEventArgs e)
{
Console.WriteLine(sender.ToString());
Console.WriteLine("向用户手机" + this.mobilenumber + "发送短信:");
Console.WriteLine( "\t您在" + e.time + "取款金额为" + e.amount);
}
}
<4>事件绑定类
//订阅系统,实现银行系统订阅几个Observer,实现与客户端的耦合
class SubscribSystem
{
public SubscribSystem(BankAccount bankAccount,Mobile mobile_object,Email email_object)
{
//现在我们在银行账户订阅2个,分别是电子邮件和手机短信
bankAccount.ProcessTran += new BankAccount.ProcessTranEventHandler(email_object.SendEmail);
bankAccount.ProcessTran += new BankAccount.ProcessTranEventHandler(mobile_object.SendNotification);
}
}
<5>主函数:产生交易,并且传达消息
public static void Main(string[] args)
{
//首先创建一个账户发布者对象
BankAccount my_account = new BankAccount("12345678910");
//两个订阅者对象
Mobile my_mobile = new Mobile("123456789");
Email my_email = new Email("123456789@qq.com");
//把这个发布者对象和订阅者对象进行绑定,传入绑定系统对象中。
//按顺序传入
SubscribSystem my_subscibSystem = new SubscribSystem(my_account, my_mobile, my_email);
Console.Write("请输入您要取款的金额:");
string amount = Console.ReadLine();
Console.WriteLine("交易成功,请取磁卡。\n");
//初始化e事件信息
UserEventArgs user = new UserEventArgs( amount);//产生一个事件的消息
//在银行账户中触发这个事件
my_account.Process(user);
Console.ReadKey();
}
}
<6>运行检查,成功