Introduction
When you develop your application, I'm sure that you have to handle several objects.
If they have to interact with the same source data, I think that you must find a way to update them with the change of data. Observer pattern is the key you can use for this solution!
Background
I have searched this website and found a few articles about the Observer pattern. And I have read some articles about event and delegate too. I want to show you - the new developers - the way to implement Observer pattern in the easiest, fastest way that is easiest to understand.
Now, let's start!
Using the Code
I created an example in Winforms, using C# language in .NET Framework 2.0.
- I have 2 forms:
Form2
and Form3
- In
form2
, there are 3 radio buttons, a Label
and a Button
. If you check the radio button, you'll see that the forecolor of label will change with the color is the name of that radio button. It's very easy, isn't it?
- When you click on button to open child form,
Form3
will show! If you check the radio button again, beside the forecolor of label change, you'll see that the backcolor of textbox in Form3 will be changed too! That's it!
- I have 2 objects in this solution:
Subject
: It will be the parent! When a client is created, the client must be registered with this subject. When something changes, the subject will notify all the clients it manages to update them.
Observer
: It's a client. When it is born, it will have to register with subject and wait to update if there's some change.
Subject Object
First, I create a delegate and an event to make it "alive" when something changes!
private delegate void NotifyHandler(string _color);
private event NotifyHandler NotifyEvent;
I also create ArrayList
names arrObs
to manage all client objects when it registers to Subject
object.
ArrayList arrObs = new ArrayList();
The full details of the subject are here:
public class Subject
{
ArrayList arrObs = new ArrayList();
private delegate void NotifyHandler(string _color);
private event NotifyHandler NotifyEvent;
public Subject()
{
this.NotifyEvent += new NotifyHandler(Notify);
}
public void UpdateClient(string _color)
{
OnNotify(_color);
}
private void OnNotify(string _color)
{
if (NotifyEvent != null)
{
NotifyEvent(_color);
}
}
private void Notify(string _color)
{
for (int i = 0; i < arrObs.Count; i++)
{
Observer obs = (Observer)arrObs[i];
obs.Update(_color);
}
}
public void RegisterClient(Observer obs)
{
arrObs.Add(obs);
}
}
You will see that when the subject is created, it will register the NotifyEvent
with Notify
method. In Notify()
, it passes the _color
string to all the clients in arrObs
. And clients will call Update
method to update the color.
Now, let's see the client object names Observer!
Observer Object
Same as Subject
object, I will define a delegate and an event to make it alive when subject notifies them!
private delegate void ColorEventHandler(string _color);
private event ColorEventHandler ColorChangedEvent;
Like the subject, when subject notifies to observer (in Update
method above), the ColorChangedEvent
will be fired and call ColorEventHander
to pass the _color
string to update!
In this solution, I want to update the back color of Form3
. So, this observer object will be created in form3
and pass the textbox
object to observer in constructor:
private TextBox txt;
public Observer(TextBox _txt)
{
this.ColorChangedEvent += new ColorEventHandler(Observer_ColorChangedEvent);
this.txt = _txt;
}
The full details of Observer
object will be here:
public class Observer
{
private delegate void ColorEventHandler(string _color);
private event ColorEventHandler ColorChangedEvent;
private TextBox txt;
public Observer(TextBox _txt)
{
this.ColorChangedEvent += new ColorEventHandler(Observer_ColorChangedEvent);
this.txt = _txt;
}
private void OnChange(string _color)
{
if (ColorChangedEvent != null)
{
ColorChangedEvent(_color);
}
}
public void Update(string _color)
{
OnChange(_color);
}
private void Observer_ColorChangedEvent(string _color)
{
switch (_color)
{
case "RED":
txt.BackColor = Color.Red;
break;
case "BLUE":
txt.BackColor = Color.Blue;
break;
case "GREEN":
txt.BackColor = Color.Green;
break;
default:
txt.BackColor = Color.Gray;
break;
}
}
}
Form2
When radio button is checked, it changed! It will call the Subject
object to update its client.
private void rdRed_CheckedChanged(object sender, EventArgs e)
{
if (rdRed.Checked)
{
objSub.UpdateClient("RED");
lblText.ForeColor = Color.Red;
}
}
private void rdGreen_CheckedChanged(object sender, EventArgs e)
{
if (rdGreen.Checked)
{
objSub.UpdateClient("GREEN");
lblText.ForeColor = Color.Green;
}
}
private void rdBlue_CheckedChanged(object sender, EventArgs e)
{
if (rdBlue.Checked)
{
objSub.UpdateClient("BLUE");
lblText.ForeColor = Color.Blue;
}
}
When you click on Button to create and open Form3
, there is a subject object name objSub
that was created in form and passed to form3
through the constructor:
private Subject objSub;
private Form3 frm;
public Form2()
{
InitializeComponent();
objSub = new Subject();
}
private void btnOpen_Click(object sender, EventArgs e)
{
frm = new Form3(objSub);
frm.Show();
}
Form3
Only create a new Observer object and register it with the objSub
public Form3(Subject _objSub)
{
InitializeComponent();
objSub = _objSub;
obs = new Observer(this.textBox1);
objSub.RegisterClient(obs);
}
That's all! When you click on the radio button, it will call the subject to update clients in its arraylist
. The client will be notified and will update the background of textbox
with the color passed through by the subject.
Points of Interest
It is compact to implement Observer pattern in an easy example! Hope you can understand and learn how to solve your problem from this small example!
Feel free to contact me!
Name: Nguyen Anh Vu(Mr.)
Email: vuna209@gmail.com
Mobile: +84984886940
Addr: 7 floor, 53 Quang Trung, Hanoi, VietNam.