Skip to content

Instantly share code, notes, and snippets.

@rbwestmoreland
Created December 13, 2011 02:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rbwestmoreland/1470171 to your computer and use it in GitHub Desktop.
Save rbwestmoreland/1470171 to your computer and use it in GitHub Desktop.
Properly Implementing the Observer Pattern
using System;
using System.Collections.Generic;
/// <summary>
/// An example Observer pattern.
/// <para>The Observer pattern is a behavioral
/// pattern, whose purpose is to define a one-to-many
/// dependency between objects where a state change
/// in one object results with all its dependents
/// being notified and updated automatically.</para>
/// </summary>
public class Observer : IDisposable
{
#region Property(s)
/// <summary>
/// Keep track of items you subscribe.
/// Otherwise, we will not be able unsubscribe.
/// </summary>
protected List<Subject> Subjects { get; set; }
#endregion Property(s)
#region Constructor(s)
public Observer()
{
Subjects = new List<Subject>();
}
#endregion Constructor(s)
#region Member(s)
public void Subscibe(Subject subject)
{
// Subscribe to the event
subject.OnPropertyChanged += OnSubjectPropertyChanged;
// Keep track of the subscription.
Subjects.Add(subject);
}
protected void OnSubjectPropertyChanged(Object sender, EventArgs args)
{
//Do Work
}
#region Disposable Member(s)
private bool Disposed { get; set; }
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!Disposed)
{
if (disposing)
{
// Make sure to unsubscribe
foreach (Subject subject in Subjects)
{
subject.OnPropertyChanged -= OnSubjectPropertyChanged;
}
}
Disposed = true;
}
}
#endregion Disposable Member(s)
#endregion Member(s)
}
using System;
public class Subject
{
#region Event(s)
public event EventHandler<EventArgs> OnPropertyChanged;
#endregion Event(s)
#region Property(s)
private String _Property = String.Empty;
public String Property
{
get
{
return _Property;
}
set
{
if (value != _Property)
{
RaiseOnPropertyChangedEvent();
}
_Property = value;
}
}
#endregion Property(s)
#region Member(s)
private void RaiseOnPropertyChangedEvent()
{
// Before we raise event, make local copy of the event / delegate.
var target = OnPropertyChanged;
// The above copy operation is tread-safe,
// thus the following check will be.
if (target != null)
{
target(this, new EventArgs());
}
}
#endregion Member(s)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment