|
委托與很多設(shè)計(jì)模式都有著千絲萬縷的聯(lián)系,在前面的隨筆中已經(jīng)介紹了委托與策略模式的聯(lián)系,本節(jié)主要來討論委托與其他兩個(gè)模式:觀察者模式和模板方法模式。
委托與觀察者模式
在.NET中,很多設(shè)計(jì)模式得到了廣泛應(yīng)用,如foreach關(guān)鍵字實(shí)現(xiàn)了迭代器模式。同樣的,.NET中也內(nèi)置了觀察者模式的實(shí)現(xiàn)方式,這種方式就是委托。
觀察者模式的一般實(shí)現(xiàn)
網(wǎng)上可以找到很多資料介紹觀察者模式的實(shí)現(xiàn),我這里介紹一種簡(jiǎn)單的退化后的觀察者模式,即Subject類為具體類,在其之上不再進(jìn)行抽象。
public class Subject{ private List<Observer> observers = new List<Observer>(); private string state; public string State { set { state = value; NotifyObservers(); } get { return state; } } public void RegisterObserver(Observer ob) { observers.Add(ob); } public void RemoveObserver(Observer ob) { observers.Remove(ob); } public void NotifyObservers() { foreach (Observer ob in observers) ob.Update(this); }}public abstract class Observer{ public abstract void Update(Subject subject);}public class ConsoleObserver : Observer{ public ConsoleObserver(Subject subject) { subject.RegisterObserver(this); } public override void Update(Subject subject) { Console.WriteLine("Subject has changed its state : " + subject.State); }}
調(diào)用的方法很簡(jiǎn)單:
Subject subject = new Subject();Observer observer = new ConsoleObserver(subject);subject.State = "Kirin Yao";
Subject類維護(hù)一個(gè)列表,負(fù)責(zé)觀察者的注冊(cè)和移除。當(dāng)其狀態(tài)發(fā)生改變時(shí),就調(diào)用NotifyObservers方法通知各個(gè)觀察者。
觀察者模式的委托實(shí)現(xiàn)
在.NET中,使用委托可以更簡(jiǎn)單更優(yōu)雅地實(shí)現(xiàn)觀察者模式。在上一篇隨筆中,最后的示例其實(shí)就是一個(gè)觀察者模式。MainForm為Subject,SubForm為Observer。當(dāng)MainForm的狀態(tài)發(fā)生改變時(shí)(即點(diǎn)擊“傳值”按鈕時(shí)),SubForm作為觀察者響應(yīng)來自MainForm的變化。
與上例對(duì)應(yīng)的,用委托實(shí)現(xiàn)的觀察者模式的代碼大致如下:
namespace DelegateSample{ class UpdateEventArgs : EventArgs { } class Subject { private string state; public string State { get { return state; } set { state = value; OnUpdate(new UpdateEventArgs()); } } public event EventHandler<UpdateEventArgs> Update; public void ChangeState(string state) { this.State = state; OnUpdate(new UpdateEventArgs()); } private void OnUpdate(UpdateEventArgs e) { EventHandler<UpdateEventArgs> handler = Update; if (handler != null) Update(this, e); } } abstract class Observer { public Subject Subject { get; set; } public Observer(Subject subject) { this.Subject = subject; this.Subject.Update += new EventHandler<UpdateEventArgs>(Subject_Update); } protected abstract void Subject_Update(object sender, UpdateEventArgs e); } class ConsoleObserver : Observer { public ConsoleObserver(Subject subject) : base(subject) { } protected override void Subject_Update(object sender, UpdateEventArgs e) { Subject subject = sender as Subject; if (subject != null) Console.WriteLine("Subject has changed its state : " + subject.State); } } class Program { static void Main(string[] args) { Subject subject = new Subject(); Observer ob = new ConsoleObserver(subject); subject.State = "Kirin Yao"; Console.ReadLine(); } }}
相比傳統(tǒng)的觀察者模式的實(shí)現(xiàn)方式(在Subject中維護(hù)一個(gè)Observer列表),使用委托避免了Subject與Observer之間的雙向引用,Subject作為主題類,對(duì)觀察者毫無所知,降低了耦合性,語法上也更加優(yōu)雅。
委托與模板方法模式
模板方法模式封裝了一段通用的邏輯,將邏輯中的特定部分交給子類實(shí)現(xiàn)。
public abstract class AbstractClass{ public void Arithmetic() { SubArithmeticA(); SubArithmeticB(); SubArithmeticC(); } protected abstract void SubArithmeticA(); protected abstract void SubArithmeticB(); protected abstract void SubArithmeticC();}public class ConcreteClass : AbstractClass{ protected override void SubArithmeticA() { //... } protected override void SubArithmeticB() { //... } protected override void SubArithmeticC() { //... }}
然而這種繼承方式的模板方法耦合度較高,特別是如果邏輯與其外部實(shí)現(xiàn)沒有必然的從屬關(guān)系的時(shí)候,用傳統(tǒng)的模板方法就顯得不那么合適了。
在某種程度上,委托可以看做是一個(gè)輕量級(jí)的模板方法實(shí)現(xiàn)方式,它將邏輯中的特定部分轉(zhuǎn)交給注冊(cè)到委托的方法來實(shí)現(xiàn)。從而替代了繼承方式的模板方法模式中,在子類中實(shí)現(xiàn)特定邏輯的方式。
public delegate void SubArithmetic();public class ConcreteClass{ public void Arithmetic() { if (SubArithmetic != null) SubArithmetic(); } public SubArithmetic SubArithmetic { get; set; }}
而SubArithmetic的實(shí)現(xiàn)交給外部:
ConcreteClass concrete = new ConcreteClass();concrete.SubArithmetic = Program.SomeMethod;concrete.Arithmetic();
咋一看在客戶端中編寫委托的方法似乎還略顯麻煩,但值得注意的是,匿名方法和Lambda表達(dá)式為我們提供了更加簡(jiǎn)便的委托語法。在函數(shù)式編程日益盛行的今天,我們應(yīng)該為.NET提供的這種語言特性而感到慶幸。
NET技術(shù):把委托說透(4):委托與設(shè)計(jì)模式,轉(zhuǎn)載需保留來源!
鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請(qǐng)第一時(shí)間聯(lián)系我們修改或刪除,多謝。