Professional Documents
Culture Documents
Session
Using Software Design Patterns
Bill Anderson
billa@andersonfiles.com
Overview
One of the hallmarks of a successful application is the adaptability to
change to new and updated requirements. This flexibility isn’t inherent –
it should be planned in the application’s design phase. Using Software
Design Patterns in your development will provide the foundation for
handling these unexpected requirements. This session presents many
useful design patterns that can lead to more flexible applications.
To repeat, you’re familiar with patterns. Let’s see how software design
patterns are used to solve specific design problems.
We’ll illustrate the Bridge Pattern with a simple example. Here’s a typical
line of VFP code:
What could be wrong with this line of code? We’ll look this line with a little
more detail…
Bridge Types
oContainer.SetAll([Tag], [Test])
Function Export
WITH THIS
LOCAL llExported
llExported = .f.
.cExportFile = .GetFileToExport()
IF .OpenFileToExport(.cExportFile) && abstract operation method
IF .BeforeExportFile(.cExportFile) && hook operation
llExported = ExportFile(.cExportFile) && abstract operation method
.AfterExportFile(.cExportFile, llExported) && hook operation
ENDIF .BeforeExportFile(.cExportFile)
ENDIF .OpenFileToExport(.cExportFile)
.CloseFileToExport(.cExportFile)
IF NOT llExported
.WriteError()
ENDIF NOT llExported
RETURN llExported
ENDWITH
Iterator Pattern
Definition: Provide a way to access the elements of an
aggregate object sequentially without exposing its underlying
representation.
Heuristic: The mechanism of traversing and accessing a
common set of objects should be separated from the objects
being traversed.
If you’ve ever traversed an array, then you’re familiar with the concepts
behind the Iterator pattern.
The Collection base class was added to Visual FoxPro 8. This base class
provides the basic functionality of the Iterator pattern. The collection base
class is a container object whose contained members are referenced by
number or by a passed index to the Item method. Members can be added
via the Add method and removed via the Remove method. Members can
be sorted as needed through the KeySort method property and traversed
via a FOR or FOR EACH loop.
Note that the objects being referenced have no knowledge of being
contained within a collection – even if the contained members are also
collections!
The Observer pattern has characteristics of both the Bridge and the
Iterator patterns. State management is abstracted from the objects that
react to changes in state management so the two can vary
independently. Once such a state management change occurs, the
Observer object iterates through the collected objects and passes the
message to the managed objects.
There are two different types of Observers, Active (also known as Voyeur)
and Passive (also known as Publish-Subscribe). The difference can be
shown the following task: Given a form that uses a private data session
and contains Save and Cancel buttons, we only want these buttons to be
enabled if the underlyingrecord has been changed.
Assume that the Save and Cancel buttons are members of an Iterator
object (by definition a collection) that should react to the dirtied buffer.
Voyeur Object: Use a timer. At each interval this global timer object will
grab a reference to the active form, determine the form’s data session,
keep track of the current buffer status and determine if the status has
changed. If the state has changed, pass the state change message to the
relevant Iterator object, enabling or disabling the controls.
Note that the voyeur (Timer) has no knowledge of the objects reacting to
the state change and does not reside on the form.
Publish/Subscribe: Objects that can dirty the buffer (textboxes, list boxes,
etc.) have a hook method in the KeyPress event that calls a global
KeyPress handler object. Every time a key is pressed, control passes to
the global KeyPress handler. The buffer is checked. If the state has
changed, pass the state change message to the relevant Iterator object,
enabling or disabling the controls.
Note that the publisher (KeyPress handler) has no knowledge of the
objects reacting to the state change and does not reside on the form.
This (somewhat artificial) example shoes the difference between an active
and passive Observer object.
The SuperClass toolbar is a classic example of the Voyeur pattern.
The Mediator Pattern is used when a central object can be used to handle
event notification. The Mediator is a form of a Passive Observer; it acts as
a communication hub that serves to promote loose coupling of objects.
Example: One of the most common examples of the Mediator pattern is
an object to manage all the open forms within an application. To populate
the forms manager, all forms add references to themselves to the forms
manager upon instantiation. When a form is destroyed, a call is made to
the forms manager to remove the reference.
Assume that we have several open forms. If a message is received to
close all the open form in the application (usually sent by a Close All
menu bar), the Forms manager can iterate through the references and
close all of the open forms.
loPinkWidget = CREATEOBJECT([myPinkWidget])
In this example myPinkWidget is the class name of the pink widget. Using
the Abstract Factory, we would code it something like this:
loPinkWidget = oFactory.GetClass([PinkWidget])
Abstract Factory
http://fox.wikis.com/wc.dll?Wiki~AbstractFactory
http://download.microsoft.com/download/vfox60/Install/6.0/W9X2K/EN-
US/Oakleaf.zip (code sample)
http://www.dofactory.com/Patterns/PatternAbstract.aspx
http://c2.com/cgi/wiki?AbstractFactoryPattern
FoxTalk, March 2002, Andy Kramek and Marcia Akins, The Kit Box: As a
Matter of Fact—ory
Credits
Many thanks are due to the people whom have previously published
and/or spoken about design patterns in the Visual FoxPro community.
These include Steven Black, Jeffrey Donnici, Yair Alan Griver, Mary
Hintemeyer, Rick Hodder and Andy Kramek.