Ä Hin
thc đối s s kin tùy biến
Í Khi dng lên mt s kin, bn cn truyn mt trng thái đặc-trưng-s-kin
cho các phương thc th lý s kin.
To mt lp đối s s kin tùy biến dn xut t lp System.EventArg. Khi
dng lên s kin, hãy to mt th hin ca lp đối s s kin và truyn nó cho
các phương thc th lý s kin.
Khi khai báo các kiu s kin, thông thường bn s cn truyn trng thái đặc-trưng-s-
kin cho các phương thc th lý s kin. Để to mt lp đối s s kin tùy biến tuân theo
mu Event do .NET Framework định nghĩa, bn cn:
1. Dn xut lp đối s s kin tùy biến t lp EventArgs. Lp EventArgs không cha
d liu và được s dng cùng vi các s kin không cn truyn trng thái.
2. Đặt mt tên có ý nghĩa cho lp đối s s kin tùy biến, kết thúc bng t EventArgs;
chng hn, DiskFullEventArgs hay MailReceivedEventArgs.
3. Đánh du lp đối s s kin là sealed nếu bn không mun các lp đối s s kin
khác có th tha kế nó.
4. Hin thc thêm các thuc tính và các thành viên d liu để h tr trng thái s kin
mà bn cn truyn cho các phương thc th lý s kin. Tt nht là làm cho trng
thái s kin trn bt biến (immutable), như vy bn nên s dng các thành viên
d liu private readonly và s dng các thuc tính public để cho phép truy xut ch-
đọc đến các thành viên d liu này.
5. Hin thc mt phương thc khi dng public h tr cu hình ban đầu ca trng thái
s kin.
6. Làm cho lp đối s s kin ca bn tr nên kh-tun-t-hóa (serializable) để b
thc thi có th marshal các th hin ca nó qua các biên min ng dng và biên
máy. Áp dng đặc tính System.SerializableAttribute thường là đã đủ cho các lp đối
s s kin. Tuy nhiên, nếu lp đối s s kin có các yêu cu tun t hóa đặc bit,
bn phi hin thc giao din System.Runtime.Serialization.ISerializable (xem mc
16.1 để biết cách làm cho mt lp tr nên kh-tun-t-hóa).
Đon mã dưới đây trình bày mt lp đối s s kin tùy biến có tên là
MailReceivedEventArgs. Gi s có mt mail-server truyn các th hin ca lp
MailReceivedEventArgs cho các phương thc th lý s kin nhn mt thông đip e-mail.
Lp này cha các thông tin v người gi và ch đề ca thông đip e-mail.
using System;
[Serializable]
public sealed class MailReceivedEventArgs : EventArgs {
// Các thành viên private readonly gi trng thái s kin
// (được phân b cho tt c các phương thc th lý s kin).
// Lp MailReceivedEventArgs s cho biết ai đã gi mail
// và ch đề là gì.
private readonly string from;
private readonly string subject;
// Phương thc khi dng (khi to trng thái s kin).
public MailReceivedEventArgs(string from, string subject) {
this.from = from;
this.subject = subject;
}
// Các thuc tính ch-đọc cho phép truy xut
// trng thái s kin.
public string From { get { return from; } }
public string Subject { get { return subject; } }
}
Ä Hin
thc mu Singleton
Í Bn cn bo đảm ch có mt th hin ca mt kiu tn ti mt thi đim cho
trước và th hin đó là kh-truy-xut đối vi tt c các phn t ca ng dng.
Hin thc kiu này theo mu Singleton như sau:
7. Hin thc mt thành viên tĩnh private để gi mt tham chiếu đến th hin
ca kiu.
8. Hin thc mt thuc tính tĩnh kh-truy-xut-công-khai để cho phép truy
xut ch-đọc đến th hin.
9. Hin thc mt phương thc khi dng private để mã lnh không th to
thêm các th hin ca kiu.
Trong tt c các mu được biết đến, có l mu Singleton được biết đến nhiu nht và
thường được s dng nht. Mc đích ca mu Singleton là bo đảm ch có mt th hin
ca mt kiu tn ti mt thi đim cho trước và cho phép truy xut toàn cc đến các
chc năng ca th hin đó. Đon mã dưới đây trình bày mt hin thc ca mu Singleton
cho mt lp có tên là SingletonExample:
public class SingletonExample {
// Thành viên tĩnh dùng để gi mt tham chiếu đến th hin singleton.
private static SingletonExample instance;
// Phương thc khi dng tĩnh dùng để to th hin singleton.
// Mt cách khác là s dng "Lazy Initialization" trong
// thuc tính Instance.
static SingletonExample () {
instance = new SingletonExample();
}
// Phương thc khi dng private dùng để ngăn mã lnh to thêm
// các th hin ca kiu singleton.
private SingletonExample () {}
// Thuc tính public cho phép truy xut đến th hin singleton.
public static SingletonExample Instance {
get { return instance; }
}
// Các phương thc public cung cp chc năng ca singleton.
public void SomeMethod1 () { /*..*/ }
public void SomeMethod2 () { /*..*/ }
}
Để gi các chc năng ca lp SingletonExample, bn có th ly v mt tham chiếu đến
singleton bng thuc tính Instance và ri gi các phương thc ca nó. Bn cũng có th
trc tiếp thc thi các thành viên ca singleton thông qua thuc tính Instance. Đon mã
dưới đây trình bày c hai cách này:
// Thu ly tham chiếu đến singleton và gi mt phương thc ca nó.
SingletonExample s = SingletonExample.Instance;
s.SomeMethod1();
// Thc thi chc năng ca singleton mà không cn tham chiếu.
SingletonExample.Instance.SomeMethod2();
Ä Hin
thc mu Observer
Í Bn cn hin thc mt cơ chế hiu qu để mt đối tượng (subject) báo vi các
đối tượng khác (observer) v nhng thay đổi trng thái ca nó.
Hin thc mu Observer bng các kiu y nhim (đóng vai trò là các con tr
hàm an-toàn-v-kiu-d-liu—type-safe function pointer) và các kiu s kin.
Cách truyn thng khi hin thc mu Observer là hin thc hai giao din: mt để t
observer (IObserver) và mt để mô t subject (ISubject). Các đối tượng có hin thc
IObserver s đăng ký vi subject, cho biết chúng mun được thông báo v các s kin
quan trng (như thay đổi trng thái) tác động đến subject. Subject chu trách nhim qun
lý danh sách các observer đã đăng ký và thông báo vi chúng khi đáp ng các s kin tác
động đến subject. Subject thường thông báo vi observer bng phương thc Notify (được
khai báo trong giao din IObserver). Subject có th truyn d liu cho observer trong
phương thc Notify, hoc observer có th cn gi mt phương thc được khai báo trong
giao din ISubject để thu ly thêm các chi tiết v s kin.
Mc dù bn có th hin thc mu Observer bng C# theo cách va được mô t, nhưng vì
mu Observer quá ph biến trong các gii pháp phn mm hin đại nên C# và .NET
Framework cung cp các kiu s kin và y nhim để đơn gin hóa hin thc ca nó. S
dng s kin và y nhim nghĩa là bn không cn khai báo giao din IObserver và
ISubject. Ngoài ra, bn không cn hin thc các logic cn thiết để qun lý và thông báo
vi các observer đã đăng ký—đây chính là phn d xy ra li nht khi viết mã.
.NET Framework s dng mt hin thc cho mu Observer da-trên-s-kin và da-trên-
y-nhim thường xuyên đến ni nó được đặt mt cái tên: mu Event. File
ObserverExample.cs cha mt hin thc cho mu Event. Ví d này bao gm:
10. Lp Thermostat (subject)—theo dõi nhit độ hin ti và thông báo vi observer khi
có s thay đổi nhit độ.
11. Lp TemperatureChangeEventArgs—là mt hin thc tùy biến ca lp
System.EventArgs, được s dng để đóng gói d liu cn phân b cho observer.
12. y nhim TemperatureEventHandler—định nghĩa ch ký ca phương thc mà tt
c các observer ca đối tượng Thermostat phi hin thc, và đối tượng Thermostat
s gi phương thc này trong s kin thay đổi nhit độ.
13. Lp TemperatureChangeObserver và TemperatureAverageObserver—là các
observer ca lp Thermostat.
Lp TemperatureChangeEventArgs (được trình bày bên dưới) dn xut t lp
System.EventArgs. Lp này s cha tt c các d liu cn thiết để subject truyn cho các
observer khi nó thông báo vi chúng v mt s kin. Nếu không cn truyn d liu, bn
không phi định nghĩa mt lp đối s mi (bn ch cn truyn đối s null khi dng nên s
kin). Xem mc 16.8 để biết rõ hơn v cách hin thc lp đối s s kin tùy biến.
// Lp đối s s kin cha thông tin v s kin thay đổi nhit độ.
// Mt th hin ca lp này s được truyn cùng vi mi s kin.
public class TemperatureChangeEventArgs : System.EventArgs {
// Các thành viên d liu cha nhit độ cũ và mi.
private readonly int oldTemperature, newTemperature;
// Phương thc khi dng (nhn giá tr nhit độ cũ và mi).
public TemperatureChangeEventArgs(int oldTemp, int newTemp) {
oldTemperature = oldTemp;
newTemperature = newTemp;
}
// Các thuc tính dùng để truy xut các giá tr nhit độ.
public int OldTemperature { get { return oldTemperature; } }
public int NewTemperature { get { return newTemperature; } }
}
Đon mã dưới đây trình bày cách khai báo y nhim TemperatureEventHandler. Da trên
khai báo này, tt c các observer phi hin thc mt phương thc (tên không quan trng),
tr v void và nhn hai đối s: mt đối tượng Thermostat và mt đối tượng
TemperatureChangeEventArgs. Trong quá trình thông báo, đối s Thermostat ch đến đối
tượng Thermostat đã dng nên s kin, và đối s TemperatureChangeEventArgs cha
các d liu v nhit độ cũ và mi.
// y nhim cho biết ch ký mà tt c các phương thc
// th lý s kin phi hin thc.
public delegate void TemperatureEventHandler(Thermostat s,
TemperatureChangeEventArgs e);
Lp Thermostat là đối tượng b giám sát trong mu Observer (Event) này. Theo lý thuyết,
mt thiết b giám sát thiết lp nhit độ hin ti bng cách gi thuc tính Temperature trên
mt đối tượng Thermostat. Khi đó, đối tượng Thermostat dng nên s kin
TemperatureChange và gi mt đối tượng TemperatureChangeEventArgs đến mi
observer. Dưới đây là mã lnh cho lp Thermostat:
// Lp mô t mt b n nhit, là ngun gc ca các s kin thay đổi
// nhit độ. Trong mu Observer, đối tượng Thermostat là subject.
public class Thermostat {
// Trường private dùng để gi nhit độ hin ti.
private int temperature = 0;