1. .Net可以很好地支持委托,事件,用事件来实现观察者模式很简洁,最大程度地减少了观察者与Subject之间的耦合。
class Subject { public delegate void ChangedEventHandler(object sender, EventArgs args); public event ChangedEventHandler Changed; public void FireTest() { if (this.Changed != null) { this.Changed(this, null); } } } class Observer { public void subject_Changed(object sender, EventArgs args) { // do something //..... this.Render(); } private void Render() { Console.WriteLine("start to reder by the model changes."); } } class Program { static void Main(string[] args) { Subject subject = new Subject(); Observer observer = new Observer(); subject.Changed += observer.subject_Changed; subject.FireTest(); } }
2. 下面的例子是一个同事用模板实现的观察者模式:
ISubject
public interface IObserver<in TChange> { void Update(TChange changes); }
subject
public class Subject<TChange> : ISubject<TChange> { protected ICollection<IObserver<TChange>> Observers = new HashSet<IObserver<TChange>>(); public void Attach(IObserver<TChange> observer) { Observers.Add(observer); } public void Dettach(IObserver<TChange> observer) { Observers.Remove(observer); } public void NotifyObservers(TChange changes) { foreach (IObserver<TChange> observer in Observers) { observer.Update(changes); } } }
IObserver
public interface IObserver<in TChange> { void Update(TChange changes); }
Client program
public class WeatherData : Subject<Tuple<string, float>> { private float temperature; public float Temperature { get { return temperature; } set { if (value != temperature) { temperature = value; this.NotifyObservers(Tuple.Create("Temperature", value)); } } } private float pressure; public float Pressure { get { return pressure; } set { if (value != pressure) { pressure = value; this.NotifyObservers(Tuple.Create("Pressure", value)); } } } private float humidity; public float Humidity { get { return humidity; } set { if (value != humidity) { humidity = value; this.NotifyObservers(Tuple.Create("Humidity", value)); } } } } public class WeatherDisplay : Label, QiHe.CodeLib.DesignPatterns.IObserver<Tuple<string, float>> { public void Update(Tuple<string, float> changes) { if (this.InvokeRequired) { this.Invoke(new Action(() => Display(changes))); } else { Display(changes); } } private void Display(Tuple<string, float> data) { this.Text = string.Format("{0}: {1:F2}", data.Item1, data.Item2); } } public class Test { [STAThread] static void Main() { WeatherData weatherData = new WeatherData(); WeatherDisplay dispalay = new WeatherDisplay(); WeatherDisplay dispalay2 = new WeatherDisplay(); weatherData.Attach(dispalay); weatherData.Attach(dispalay2); dispalay2.Top = 50; Form form = new Form(); dispalay.AutoSize = true; form.Controls.Add(dispalay); form.Controls.Add(dispalay2); //new Thread(() => form.ShowDialog()).Start(); form.Show(); weatherData.Temperature = 20; Console.ReadLine(); weatherData.Pressure = 80; Console.ReadLine(); weatherData.Humidity = 0.4f; Console.ReadLine(); } }