标签:style blog http color ar os 使用 sp for
委托与很多设计模式都有着千丝万缕的联系,在前面的随笔中已经介绍了委托与策略模式的联系,本节主要来讨论委托与其他两个模式:观察者模式和模板方法模式。
在.NET中,很多设计模式得到了广泛应用,如foreach关键字实现了迭代器模式。同样的,.NET中也内置了观察者模式的实现方式,这种方式就是委托。
网上可以找到很多资料介绍观察者模式的实现,我这里介绍一种简单的退化后的观察者模式,即Subject类为具体类,在其之上不再进行抽象。
1 public class Subject 2 { 3 private List<Observer> observers = new List<Observer>(); 4 5 private string state; 6 public string State 7 { 8 set 9 { 10 state = value; 11 NotifyObservers(); 12 } 13 get { return state; } 14 } 15 16 public void RegisterObserver(Observer ob) 17 { 18 observers.Add(ob); 19 } 20 21 public void RemoveObserver(Observer ob) 22 { 23 observers.Remove(ob); 24 } 25 26 public void NotifyObservers() 27 { 28 foreach (Observer ob in observers) 29 ob.Update(this); 30 } 31 } 32 33 public abstract class Observer 34 { 35 public abstract void Update(Subject subject); 36 } 37 38 public class ConsoleObserver : Observer 39 { 40 public ConsoleObserver(Subject subject) 41 { 42 subject.RegisterObserver(this); 43 } 44 45 public override void Update(Subject subject) 46 { 47 Console.WriteLine("Subject has changed its state : " + subject.State); 48 } 49 } 50
调用的方法很简单:
1 Subject subject = new Subject(); 2 Observer observer = new ConsoleObserver(subject); 3 subject.State = "Kirin Yao";
Subject类维护一个列表,负责观察者的注册和移除。当其状态发生改变时,就调用NotifyObservers方法通知各个观察者。
在.NET中,使用委托可以更简单更优雅地实现观察者模式。在上一篇随笔中,最后的示例其实就是一个观察者模式。MainForm为Subject,SubForm为Observer。当MainForm的状态发生改变时(即点击“传值”按钮时),SubForm作为观察者响应来自MainForm的变化。
与上例对应的,用委托实现的观察者模式的代码大致如下:
1 namespace DelegateSample 2 { 3 class UpdateEventArgs : EventArgs { } 4 5 class Subject 6 { 7 private string state; 8 9 public string State 10 { 11 get { return state; } 12 set 13 { 14 state = value; 15 OnUpdate(new UpdateEventArgs()); 16 } 17 } 18 19 public event EventHandler<UpdateEventArgs> Update; 20 21 private void OnUpdate(UpdateEventArgs e) 22 { 23 EventHandler<UpdateEventArgs> handler = Update; 24 if (handler != null) 25 Update(this, e); 26 } 27 } 28 29 abstract class Observer 30 { 31 public Subject Subject { get; set; } 32 33 public Observer(Subject subject) 34 { 35 this.Subject = subject; 36 this.Subject.Update += new EventHandler<UpdateEventArgs>(Subject_Update); 37 } 38 39 protected abstract void Subject_Update(object sender, UpdateEventArgs e); 40 } 41 42 class ConsoleObserver : Observer 43 { 44 public ConsoleObserver(Subject subject) : base(subject) { } 45 46 protected override void Subject_Update(object sender, UpdateEventArgs e) 47 { 48 Subject subject = sender as Subject; 49 if (subject != null) 50 Console.WriteLine("Subject has changed its state : " + subject.State); 51 } 52 } 53 54 class Program 55 { 56 static void Main(string[] args) 57 { 58 Subject subject = new Subject(); 59 Observer ob = new ConsoleObserver(subject); 60 subject.State = "Kirin Yao"; 61 Console.ReadLine(); 62 } 63 } 64 }
相比传统的观察者模式的实现方式(在Subject中维护一个Observer列表),使用委托避免了Subject与Observer之间的双向引用,Subject作为主题类,对观察者毫无所知,降低了耦合性,语法上也更加优雅。
模板方法模式封装了一段通用的逻辑,将逻辑中的特定部分交给子类实现。
1 public abstract class AbstractClass 2 { 3 public void Arithmetic() 4 { 5 SubArithmeticA(); 6 SubArithmeticB(); 7 SubArithmeticC(); 8 } 9 10 protected abstract void SubArithmeticA(); 11 protected abstract void SubArithmeticB(); 12 protected abstract void SubArithmeticC(); 13 } 14 15 public class ConcreteClass : AbstractClass 16 { 17 protected override void SubArithmeticA() 18 { 19 //... 20 } 21 22 protected override void SubArithmeticB() 23 { 24 //... 25 } 26 27 protected override void SubArithmeticC() 28 { 29 //... 30 } 31 }
然而这种继承方式的模板方法耦合度较高,特别是如果逻辑与其外部实现没有必然的从属关系的时候,用传统的模板方法就显得不那么合适了。
在某种程度上,委托可以看做是一个轻量级的模板方法实现方式,它将逻辑中的特定部分转交给注册到委托的方法来实现。从而替代了继承方式的模板方法模式中,在子类中实现特定逻辑的方式。
1 public delegate void SubArithmetic(); 2 3 public class ConcreteClass 4 { 5 public void Arithmetic() 6 { 7 if (SubArithmetic != null) 8 SubArithmetic(); 9 } 10 11 public SubArithmetic SubArithmetic { get; set; } 12 }
而SubArithmetic的实现交给外部:
1 ConcreteClass concrete = new ConcreteClass(); 2 concrete.SubArithmetic = Program.SomeMethod; 3 concrete.Arithmetic();
咋一看在客户端中编写委托的方法似乎还略显麻烦,但值得注意的是,匿名方法和Lambda表达式为我们提供了更加简便的委托语法。在函数式编程日益盛行的今天,我们应该为.NET提供的这种语言特性而感到庆幸。
本文重点讨论委托与设计模式的关系,包括观察者模式和模板方法模式。您是否觉得委托与其他方法也有关系呢?不妨在回复中进行讨论。
到此为止,我们共发布了4篇随笔,讨论委托及其相关概念。其他三篇的链接如下:
标签:style blog http color ar os 使用 sp for
原文地址:http://www.cnblogs.com/XingchenStudio/p/4096789.html