|
using System;
using System.Collections.Specialized;
using System.Collections;
using System.Windows.Forms;
using System.Drawing;
namespace Rockprint.Patterns.Custom.Observer
{
/// <summary>
/// Classic Pattern IObserver interface
/// </summary>
public interface IObserver
{
/// <summary>
/// The Update() method will be called when a ISubject "notifies" it via <seealso cref="ISubject"/>
/// </summary>
void Update(Object newData);
}
/// <summary>
/// Classic Pattern ISubject interface
/// </summary>
public interface ISubject
{
/// <summary>
/// Attaches the specified observer to the list of observers to be notified.
/// </summary>
/// <param name="observer"></param>
void Attach(IObserver observer);
/// <summary>
/// Detaches the specified observer to the list of observers to be notified.
/// </summary>
/// <param name="observer"></param>
void Detach(IObserver observer);
/// <summary>
/// Notifies all "attached" observers
/// </summary>
void Notify(Object newData);
}
/// <summary>
/// Concrete implementation of ISubject
/// </summary>
public class SubjectBase : ISubject
{
#region ISubject Members
ArrayList _observers = new ArrayList();
public void Attach(IObserver observer)
{
// SubjectBase.Attach implementation
_observers.Add(observer);
}
public void Detach(IObserver observer)
{
// SubjectBase.Detach implementation
_observers.Remove(observer);
}
public void Notify(Object newData)
{
// SubjectBase.Notify implementation
foreach(IObserver o in _observers)
o.Update(newData);
}
#endregion
protected object _subject;
public object Subject
{
get
{ return _subject; }
set
{
_subject = value;
Notify(value);
}
}
}
// Some base datatype subjects to derive from
public class StringSubject : SubjectBase
{
public StringSubject(string value)
{
base.Subject = value;
}
//protected new string _subject;
public new string Subject
{
get
{ return (string) base.Subject; }
set
{
base._subject = value;
base.Notify(value);
}
}
}
public class LongSubject : SubjectBase
{
public LongSubject(long value)
{
base.Subject = value;
}
//protected new string _subject;
public new long Subject
{
get
{ return (long) base.Subject; }
set
{
base._subject = value;
base.Notify(value);
}
}
}
public class IntSubject : SubjectBase
{
public IntSubject(int value)
{
base.Subject = value;
}
//protected new string _subject;
public new int Subject
{
get
{ return (int) base.Subject; }
set
{
base._subject = value;
base.Notify(value);
}
}
}
public class BoolSubject : SubjectBase
{
public BoolSubject(bool value)
{
base.Subject = value;
}
//protected new string _subject;
public new bool Subject
{
get
{ return (bool) base.Subject; }
set
{
base._subject = value;
base.Notify(value);
}
}
}
public class DateSubject : SubjectBase
{
public DateSubject(DateTime value)
{
base.Subject = value;
}
//protected new string _subject;
public new DateTime Subject
{
get
{ return (DateTime) base.Subject; }
set
{
base._subject = value;
base.Notify(value);
}
}
}
/// <summary>
/// Specialised Observer class designed to observe when the GUI needs updating.
/// GUIObserver's contain references objects that implement the <see cref="IGUIUpdate">IGUIUpdate</see> interface.
/// When a GUIObserver is notififed, it's IObserver.Update method calls IGUIUpdate.Init if required (will only be called once)
/// followed by IGUIUpdate.Reset and IGUIUpdate.Fill
/// </summary>
/// <summary>
/// Defines the three main operations required in displaying a visual control
/// Init - Initialises an empty control to a default state with no data (i.e. setting column headings but no rows)
/// Reset - Resets the control back to initalised state (may simple call Init again, or remove the items from a ListView
/// Fill - Populates the control, it is up to individual implementations to deal with gathering the data to populate the control.
///
/// Objects implementing this interface need to maintain/create there own references/pointers to the controls required to update
/// and the data required to update them.
///
/// See the example "updater" below.
/// </summary>
public interface IGUIUpdate
{
/// <summary>
/// This is the subject that control represents. If a control is cleared or changed in other programmatic ways the
/// subject may also be set.
/// </summary>
SubjectBase ControlSubject
{
get ; set;
}
/// <summary>
/// Buffer that will contain the a value sent via the Observer pattern through the notify method.
/// The value type and content will be specific to the deriving class.
/// </summary>
Object NewData
{
get; set;
}
void Init();
void Reset();
void Fill();
}
public abstract class GUIUpdateBase : IGUIUpdate
{
private SubjectBase _controlSubject;
public SubjectBase ControlSubject
{
get { return _controlSubject;}
set { _controlSubject = value;}
}
private Object _newData;
public Object NewData
{
get { return _newData;}
set { _newData = value;}
}
public abstract void Init();
public abstract void Reset();
public abstract void Fill();
}
public sealed class GUIObserver : IObserver
{
private IGUIUpdate _update;
private bool _initialised;
#region IObserver Members
public void Update(Object newData)
{
Console.WriteLine("{0}.Update called for {1}", base.GetType().ToString(), _update.GetType().ToString());
initUpdater();
_update.NewData= newData;
_update.Reset();
_update.Fill();
}
#endregion
public GUIObserver(IGUIUpdate update) : this(update, false)
{
}
public GUIObserver(IGUIUpdate update, bool initialiseNow)
{
_update = update;
if(initialiseNow)
initUpdater();
}
private void initUpdater()
{
if(!_initialised)
{
_update.Init();
_initialised = true;
}
}
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.