委託,瞭解釋出者訂閱者模型
阿新 • • 發佈:2018-12-22
一。釋出者訂閱者模型圖解。
從圖中我們看有一個部分組成?
- 釋出者
- 訂閱者
- 事件繫結
- 事件資訊
3,4部分容易混為一談,我們這裡做一個例子用於理解:
要是實現A->B貨物的運輸,需要什麼呢?需要一條能通的道路,還需要一輛運載了貨物的車。A此時就是釋出者,B是訂閱者,事件繫結就是一條能通的道路,事件資訊就是這個運載了貨物的車。如果只有事件繫結(道路)而沒有事件資訊(貨物車),就沒有可以傳輸的東西了。
二。C#中委託和事件的命名規範。
- 什麼是事件?和委託指標有區別嗎?
我認為並沒有,都可以指向多個函式。
命名語法:public event delegate 事件名; - 委託的命名規範:委託就是為了建立事件(委託指標),因此它的名字要根據事件名來設計通常是事件名Handler
- 事件資訊:這是一個不同於釋出者和訂閱者的類,通常他繼承EventArgs。
- .net桌面應用應用中經常使用的委託就是(object sender,EventArgs e)
<1>前一個引數表示訊息的釋出者
<2>後一個引數表示訊息的具體內容。
三。通過一個例項來解析這個模型。
-
我們將嚴格按照模型進行分佈講解
背景:
<1>建立一個”憨有錢“銀行的一個賬戶物件,賬戶的號碼是12345678910。
<2>建立一個手機物件,有手機號123456789,建立郵箱物件有郵箱號碼
<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("[email protected]");
//把這個釋出者物件和訂閱者物件進行繫結,傳入繫結系統物件中。
//按順序傳入
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>執行檢查,成功