Object Oriented Programming Patterns for Geeks
The Observer Pattern
namespace ooppatterns
{
using System;
using System.Collections.Generic;
internal class Program
{
private static void Main( string[] args )
{
Server SS = new Server( "Server" );
Client CC1 = new Client( "Matt", true );
SS.Connect( CC1 );
SS.Connect( new Client( "Kelly", true ) );
SS.Connect( new Client( "Tasha", false ) );
SS.Connect( new Client( "Moogie", false ) );
SS.Connect( new Client( "Achies", true ) );
SS.Connect( new Client( "Marty", false ) );
SS.Notify( "Restuarant is open.." );
CC1.NotifyServer( "Want to go for a meal?" );
SS.Notify( "Restuarant is closed.." );
CC1.NotifyServer( "Bye!" );
CC1.Disconnect();
Console.ReadLine();
}
}
delegate void NotifyHandler( IName sender, string Message );
interface IName
{
string Name { get; }
}
// this is the 'subject'
class Server : IName
{
private List<Client> _clients = new List<Client>();
private NotifyHandler _call;
private string _name;
public Server( string name )
{
this._name = name;
}
public string Name
{
get { return this._name; }
}
public void Connect( Client client )
{
client.Server = this;
this._call += client.Handle_Notify;
this._clients.Add( client );
}
public void Disconnect( Client client )
{
this._call -= client.Handle_Notify;
Console.WriteLine( "{0}\tHas disconnected!", client.Name );
client = null;
}
// Notify everyone
public void Notify( string message )
{
if ( this._call != null )
this._call( this, message );
}
public void NotifyFromClient( Client sender, string message )
{
// Ensure the sender does not get the message it sent out...
if ( this._call != null )
foreach ( Delegate blah in this._call.GetInvocationList() )
if ( sender.GetHashCode() != blah.Target.GetHashCode() )
blah.DynamicInvoke( new object[] { sender, message } );
}
public void NotifyFromClientToClient
( Client sender, Client reciever, string message )
{
// Ensure only the reciever gets the message sent to it...
if ( this._call != null )
foreach ( Delegate blah in this._call.GetInvocationList() )
if ( reciever.GetHashCode() == blah.Target.GetHashCode() )
{
blah.DynamicInvoke( new object[] { sender, message } );
break;
}
}
}
// This is the 'observer'
class Client : IName
{
private string _name;
private bool _wantsFood;
private Server _server;
public Client( string name, bool wantsfood )
{
this._name = name;
this._wantsFood = wantsfood;
}
public Server Server
{
set { this._server = value; }
}
public string Name
{
get { return this._name; }
}
// Recieve events from server and handle
public void Handle_Notify( IName sender, string message )
{
Console.WriteLine( "{1} \tnotified {0} \t= {2}",
this._name, sender.Name, message );
switch ( message )
{
case "Want to go for a meal?":
{
if ( this._wantsFood )
this.NotifySenderClient( sender, "Sure!" );
else
{
this.NotifySenderClient( sender, "Nope!" );
this.Disconnect();
}
break;
}
case "Bye!":
{
this.NotifyServer( "See you later!" );
break;
}
}
}
public void Disconnect()
{
this._server.Disconnect( this );
}
// send an event to all other clients
public void NotifyServer( string message )
{
this._server.NotifyFromClient( this, message );
}
// Send an event to a specific client
public void NotifySenderClient( IName reciever, string message )
{
this._server.NotifyFromClientToClient
( this, reciever as Client, message );
}
}
}