The observer pattern is very useful and very easy to implement. It only requires two interfaces. One interface is the subject interface the other is the Observer.
The subject contains three methods: AddObserver, RemoveObserver, and Notify. This interface is implemented by any class that needs to notify other objects that its state has changed.
Public Interface ISubject
Sub AddObserver(ByRef ob As IObserver)
Sub RemoveObserver(ByRef ob As IObserver)
Sub Notify()
End Interface
The other interface is the observer it only contains one method Update, this interface is implemented by any class that needs to be notified by the subject object.
Public Interface IObserver
Sub Update(ByVal subj As Object)
End Interface
In some examples of this pattern I have seen the subject is setup as an abstract class that you must inherit from, but I believe it limits the usefulness of the pattern. From what I read in the
Head First Design Patterns book it says it is best to program to an interface instead of using inheritance. To illustrate this pattern I have created a simple program that monitors My Documents folder on your computer and notifies a form when ever this folder's contents have changed. This is only an example, the way I implemented the subject object is a little weak but it will serve well enough.
I used the FileSystemWatcher as my base class and implemented the ISubject interface to serve as the subject. The class that implements the subject interface must contain a collection of observers the observers are added and removed using the AddObserver and RemoveObserver methods. The observers are notified by the Notify method witch iterates through the observer collection calling the Update method in the IObserver interface.
Imports System.IO
Public Class MyFileWatcher
Inherits FileSystemWatcher
Implements ISubject
Dim _observers As New ArrayList
Public Sub AddObserver(ByRef ob As IObserver) _
Implements ISubject.AddObserver
_observers.Add(ob)
End Sub
Public Sub Notify() _
Implements ISubject.Notify
Dim ob As IObserver
For Each ob In _observers
ob.Update(Me)
Next
End Sub
Public Sub RemoveObserver(ByRef ob As IObserver) _
Implements ISubject.RemoveObserver
_observers.Remove(ob)
End Sub
Private Sub File_Changed _
(ByVal sender As Object, ByVal e As System.IO.FileSystemEventArgs) Handles Me.Changed
Me.Notify()
End Sub
Private Sub File_Created _
(ByVal sender As Object, ByVal e As System.IO.FileSystemEventArgs) Handles Me.Created
Me.Notify()
End Sub
Private Sub File_Deleted _
(ByVal sender As Object, ByVal e As System.IO.FileSystemEventArgs) Handles Me.Deleted
Me.Notify()
End Sub
Private Sub file_Renamed _
(ByVal sender As Object, ByVal e As System.IO.RenamedEventArgs)Handles Me.Renamed
Me.Notify()
End Sub
End Class
The observer is implemented as a form that contains List box this list box is Notified by the Subject and the Update method is ran witch updates the list with a valid list of files.
Imports fileWatcher
Imports System.IO
Public Class Form1
Implements IObserver
Private _path As String
Private _allfiles As Collections.ObjectModel.ReadOnlyCollection(Of String)
Public Property Path() As String
Get
Return _path
End Get
Set(ByVal value As String)
_path = value
End Set
End Property
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
_allfiles = My.Computer.FileSystem.GetFiles(_path)
For Each singleFile As String In _allfiles
Me.ListBox1.Items.Add(singleFile)
Next
End Sub
Public Sub Update1(ByVal subj As Object) Implements fileWatcher.IObserver.Update
Me.ListBox1.Items.Clear()
_allfiles = My.Computer.FileSystem.GetFiles(_path)
For Each singleFile As String In _allfiles
Me.ListBox1.Items.Add(singleFile)
Next
End Sub
End Class
Lastly I created an MDI form that contains an instance of the FileWatcher class and creates a new Instance of the subject form every time a tool strip button is clicked. When ever a file in my documents is update all the child forms of the mdi are updated.
Imports System.Windows.Forms
Imports fileWatcher
Public Class MDIParent1
Private Sub ShowNewForm(ByVal sender As Object, ByVal e As EventArgs) Handles NewToolStripButton.Click
Dim FormObserver As New Form1
FormObserver.MdiParent = Me
FormObserver.Path = My.Computer.FileSystem.SpecialDirectories.MyDocuments
_fileWatcherSubject.AddObserver(FormObserver)
FormObserver.Show()
End Sub
Private Sub MDIParent1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
_fileWatcherSubject.Path = My.Computer.FileSystem.SpecialDirectories.MyDocuments
End Sub
End Class
For complete Observer pattern code download at the following link.
fileWatcher.zip (116.6 KB)