Friday, November 21, 2003

Light Relief - Sort Of


As a break from software design patterns here is a site that's funny but has a serious message. I recommend taking up their offer at the end of the video and finding stores that provide meat & poultry from sustainable and organic sources.

The Meatrix

Thursday, November 20, 2003

Singleton Pattern


Description

I once saw this pattern summarized as "There is only one Elvis and there will only ever be one Elvis". The Singleton is a pattern that is used when you want one and only one instance of an object.

The usual reasons for this are: the object encapsulates an important resource that is used in many places (for example if you don't want an application to be able to open up several connections to the database make a singleton out of the database connection), or the resource can only be used by one thread at a time (e.g., a class that plays a song file. You only want one song playing at a time.)

Example

The usual way this is implemented is by
1) declare a private static (shared in VB) variable to reference the single instance,
2) create a static method in the singleton class that returns the single instance
3) make the constructor private so the class can only be instantiated by itself.

Here is an example:


Public Class SingletonMP3Player
'1) the private variable
Private Shared _instance As SingletonMP3Player
 
'2) the static method to return the singleton
Public Shared Function GetInstance() As SingletonMP3Player
'if it has not already been instantiated then create it
If _instance Is Nothing Then
_instance = New SingletonMP3Player
End If
Return _instance
End Function
 
'3) the private constructor
Private Sub New()
'prevents instantiation from outside the class
End Sub
 
'Other methods required to make the class useful
Public Sub Play(filename As String)
'code to play, stopping self if already playing something else
End Sub
 
Public Sub StopPlaying()
'code here
End Sub
 
Public Sub OtherUserfulMethod()
'etc ...
End Sub
End Class


Here is how you could use it:


Public Class Singing
Sub SingTheBlues()
Dim myPlayer As SingletonMP3Player
myPlayer = SingletonMP3Player.GetInstance()
myPlayer.Play("c:\music\blues\Born Under A Bad Sign.mp3")
End Sub
 
Sub GrowlDemonically()
Dim myPlayer As SingletonMP3Player
myPlayer = SingletonMP3Player.GetInstance()
myPlayer.Play("c:\music\deathmetal\Blackwater Park.mp3")
End Sub
 
'or a show off way to do it
Sub JustListen()
SingletonMP3Player.GetInstance().Play("c:\music\prog\3 Min Warning.mp3")
End Sub
End Class

Resources

Wikipedia - Singleton pattern
Data & Object Factory - Singleton
DotNetExtreme - Singleton pattern

Tuesday, November 18, 2003

Prototype Pattern


Description

This is another pattern that builds objects in a way that protects the client from having to know the exact class of the required object. So when would you use it instead of Factory, Abstract Factory or Builder? My answer would be:

  1. When you have objects that take a lot of resources to create (e.g., if you have to read a file or database table to get values) but don't take a lot to clone.
  2. When you have a lot of immutable objects and you don't want to keep creating new instances but instead you want to use a single instance and pass around copies of it. (e.g., fonts - you will use a particular font a lot in a word processor program, but it can be the same instance every time.) This sounds like the "Singleton" pattern, which I'll describe next, but notice that I say "when you have a lot of immutable objects."
  3. When you have a large number of sub-classes and could instead make them into a single class only differing by the values of certain attributes. (e.g., you have several types of customer and you could sub-class them, but it is actually easier to create instances of the one class and give them different values to represent the different types. Create the PremierCustomer prototype once, loading the data that differentiates him from a CreditRiskCustomer, then copy that prototype and change the "Name", "Address", etc. values.)
  4. If there are a large variety of classes to be instantiated and the various instances differ only in certain attributes. (e.g., you have a game program and Monster, Hero, Villain, etc., classes. You can have lots of different monsters and they will differ in the graphic used to display them, their size, viciousness, etc. Rather than create a new Monster object every time simply copy the prototype and change the graphic, etc.)

(Note: Clone has two definitions: a "shallow clone" and a "deep clone". A shallow clone copies value type variables within the original but doesn't make a copy of reference type variables, it just returns the reference. I have also seen shallow clone used to mean that you return a reference to the prototype object - that's not strictly speaking a clone, but it does get used that way by some people. A deep clone copies everything within the prototype so the copy has no connection with the prototype - this usually takes a lot more resources than a shallow clone. Which method you use depends on your particular situation.)

Example

Let's say we have a system that inventories audio visual materials. To create the objects that represent the materials takes a lot of resources but to then customize them to the particular type of material (e.g., 1" tape) is relatively quick.

Lets start with the Material super-class:


Public MustInherit Class Material : Implements ICloneable
 
Public MustOverride Property Description() As String
 
'Returns a shallow clone
Public Function Clone() As Object Implements ICloneable.Clone
Return CType(Me.MemberwiseClone(), Material)
End Function
 
Public MustOverride Sub CommonMethod()
End Class


And here is a sub-class:


Public Class Tape : Inherits Material
'All sorts of complex objects that take a long time to initialize
Private TypeX As ComplexClassOfSomeKind
'etc ...
 
Public Overrides Property Description() As String
'code goes here
End Property
 
Public Overrides Sub CommonMethod()
'code here
End Sub
 
'other methods ...
End Class


Now we have the class that controls the creation of the prototypes and provides the clones:


Public Class MaterialBuilder
Private _prototypes As New Hashtable
 
Public Sub New()
InitializePrototypes()
End Sub
 
Public Sub InitializePrototypes()
'put objects of the different material sub-classes into the hashtable
_prototypes.Add("TAPE", MaterialFactory("TAPE"))
_prototypes.Add("CD", MaterialFactory("CD"))
_prototypes.Add("DVD", MaterialFactory("DVD"))
'etc ...
End Sub
 
Public Function BuildMaterial(aType As String) As Material
Dim builder As Material
builder = _prototypes.Item(aType)
Return builder.Clone()
End Function
 
Private Function MaterialFactory(aType As String) As Material
'factory code goes here
End Function
End Class


The pattern could be used like this:


Class ClientClass
Public Sub DoIt(aType As String, description As String)
Dim builder As New MaterialBuilder
Dim myMaterial As Material = builder.BuildMaterial(aType)
myMaterial.Description = description
myMaterial.CommonMethod()
'etc ...
End Sub
End Class

Resources

Wikipedia - Prototype Pattern
Data & Object Factory - Prototype Pattern
DotNetExtreme - Prototype Pattern

Friday, November 14, 2003

Builder Pattern


Description

This pattern could be described as a way of building complex objects which share common elements.

Example

Let's say we have documents that we want to provide to our clients in whatever format they require. Some clients want Word format, some want PDF, some want HTML and some want XML. We also know that in the future more formats will be required. Our documents can be broken down into elements such as document header, page header, margin width, pre-data descriptive text, data, post-data descriptive text, etc.

The builder pattern is perfect to handle this. First make sure you are familiar with the abstract factory pattern I described yesterday. Builder has many similarities to abstract factory. The main difference being that the "factories" or "toolkits" created by the abstract factory are now called "builders" and instead of providing objects for a particular domain they provide methods to build the various parts of a single complex object.

We start with an AbstractBuilder class which contains a static (shared in VB) factory method to create the builder objects that will build the documents in the various formats. It also contains abstract methods to build the various parts of the formatted document and finally a property for returning the finished document in the required format. The different document classes must use a common interface so the client code can handle them without knowing what class they are, so the property returns a type of that interface.


Public MustInherit Class AbstractDocumentBuilder
Public Shared Function GetBuilder(format As String) _
As AbstractDocumentBuilder
Select Case format.ToUpper()
Case "WORD"
Return New WordBuilder
Case "PDF"
Return New PDFBuilder
Case "XML"
Return New XMLBuilder
Case Else
Return Nothing
End Select
End Function
 
Public MustOverride Sub BuildDocHeader(docHeaderText As String)
Public MustOverride Sub BuildPageHeader(pageHeaderText As String)
Public MustOverride Sub BuildPreDataText(preDataText As String)
'more methods for other parts of the document ...
 
Public MustOverride ReadOnly Property Document() As IDocument
End Class

Note: You could give these part builder methods "do nothing" implementations so there would be no need to implement them for formats that don't have that part.

Next are the concrete builder classes for the formats:


Public Class WordBuilder : Inherits AbstractDocumentBuilder
Private _document As New WordDocument
 
Public Overrides ReadOnly Property Document() As IDocument
Get
Return _document
End Get
End Property
 
Public Overrides Sub BuildDocHeader(docHeaderText As String)
'code here for Word format
End Sub
 
Public Overrides Sub BuildPageHeader(pageHeaderText As String)
'code here for Word format
End Sub
 
Public Overrides Sub BuildPreDataText(preDataText As String)
'code here for Word format
End Sub
End Class


In my example the IDocument interface contains a method to write the document to a file. You could give it whatever methods are appropriate for your implementation. For example you could give it a "Send()" method so it emails itself to the person requesting it.


Public Interface IDocument
Sub Write(fout As FileStream)
End Interface


Next is the class representing the formatted document:


Public Class WordDocument : Implements IDocument
Public Sub Write(ByVal fout As FileStream) Implements IDocument.Write
'code to write the document to the stream
End Sub
 
'other needed methods & properties
End Class


Finally the client would contain code something like this (note: "doc" represents the original unformatted document):


Public Sub WriteDocument(format As String, fout As FileStream)
Dim finalDocument As IDocument
Dim builder As AbstractDocumentBuilder
builder = AbstractDocumentBuilder.GetBuilder(format)
builder.BuildDocHeader(doc.DocumentHeader)
builder.BuildPageHeader(doc.PageHeader)
builder.BuildPreDataText(doc.PreDataText)
'Build other parts of the document ...
 
finalDocument = builder.Document
finalDocument.Write(fout)
End Sub


To add a new format you create the builder class for it and add a 'Case "NEWDOC"' to the Select statement in the abstract builder class.
Resources

Data & Object Factory: Builder Pattern
Wikipedia - Builder Pattern
DotNetExtreme - Builder Pattern

Thursday, November 13, 2003

Abstract Factory Pattern


Description

This could be described roughly as a factory that produces factories. The usual description is a factory that produces toolkits.

Example

So what does that mean? Well, here's an example: we are consulting an entertainment company that produces movies and TV shows. Some of the classes involved would be Customer, Product, Deal, License, Market, SalesPerson. Now products can be licensed in different media such as Pay-Per-View, Premium Cable, Basic Cable, Domestic TV, International TV, etc. and the deals are very different in each media. The classes we described earlier vary across these media. For example, an international TV deal involves different languages (e.g., French, German and Italian) and many markets (e.g., France, Switzerland, Belgium, Germany, Italy), whereas a domestic TV deal involves only one language (e.g., Spanish) and one market (e.g., Los Angeles). Also the way the customers are viewed within the different media is different and the data associated with a customer is different. The sales people are paid differently and different data about them is kept in each media. So we have a set of class heirarchies something like this:


Customer
|
-----------------------------------------------
| | | |
DomesticTVCustomer IntTVCustomer PPVCustomer etc
 
 
Deal
|
--------------------------------------------
| | | |
DomesticTVDeal IntTVDeal PPVDeal etc


The code might look something like this:


Public MustInherit Class Deal
Public MustOverride Sub MakeLotsOfMoney()
'other members of deal
End Class
 
Public Class DomesticTVDeal : Inherits Deal
Public Overrides Sub MakeLotsOfMoney()
'Money making code goes here
End Sub
'etc ...
End Class
 
Public Class PPVDeal : Inherits Deal
Public Overrides Sub MakeLotsOfMoney()
'Money making code goes here
End Sub
'etc ...
End Class

And there are several other similar heirarchies for the other classes.

Now we don't want to have to write different code for every media so how can we get around it? Well, what if we create a factory that creates the objects for the different media?


Public Class MediaFactory
Public Function GetCustomer(media As MediaType) as Customer
Select Case media
Case MediaType.DOMESTIC
return New DomesticTVCustomer
Case MediaType.INTERNATIONAL
return New InternationalCustomer
Case MediaType.PPV
return New PPVCustomer
Case ETC
'etc ...
End Select
End Function
 
Public Functon GetDeal(media As Integer) as Deal
'big select statement
End Function
 
Public Function GetLicense(media As Integer) as License
'big select statement
End Function
 
'etc ...
End Class

Not bad but now we have big select statements in every method and if we add a new media we have to go into every method and add something to the select. Well, what if we make a factory that generates factories, one for each media? The resulting "factory" classes are not really factories so they often get called "toolkits". But remember that for the Factory pattern we have to create a super-class for the toolkits and then a factory class to create the toolkit objects. So let's kill two birds with one stone and put the Factory method into the super-class.

Now we have something like this:


Public MustInherit Class AbstractMediaFactory
 
Public Enum MediaType As Integer
DOMESTIC
INTERNATIONAL
PPV
'etc ...
End Enum
 
Public Shared Function GetFactory(media As MediaType) As AbstractMediaFactory
Select Case media
Case MediaType.DOMESTIC
Return New DomesticTVFactory
 
Case MediaType.INTERNATIONAL
Return New InternationalTVFactory
 
Case MediaType.PPV
Return New PPVFactory
 
Case MediaType.ETC
'etc ...
 
Case Else
Return Nothing
 
End Select
End Function
 
Public MustOverride Function GetDeal() As Deal
Public MustOverride Function GetCustomer() As Customer
Public MustOverride Function GetLicense() As License
'Other GetXXX functions go here
End Class
 
Public Class DomesticTVFactory : Inherits AbstractMediaFactory
Public Overrides Function GetDeal() As Deal
Return New DomesticTVDeal
End Function
 
Public Overrides Function GetCustomer() As Customer
Return New DomesticTVCustomer
End Function
 
Public Overrides Function GetLicense() As License
Return New DomesticTVLicense
End Function
End Class
 
Public Class PPVFactory : Inherits AbstractMediaFactory
Public Overrides Function GetDeal() As Deal
Return New PPVDeal
End Function
 
Public Overrides Function GetCustomer() As Customer
Return New PPVCustomer
End Function
 
Public Overrides Function GetLicense() As License
Return New PPVLicense
End Function
End Class

To use this pattern we first get the factory (or toolkit) we need



Dim myFactory as AbstractMediaFactory
myFactory = AbstractMediaFactory.GetFactory(media)

Then we get the specific object we want to use:


Dim theDeal as Deal
theDeal = myFactory.GetDeal()
theDeal.MakeLotsOfMoney()


Now if we want to add a new media we simply create the classes and toolkit class for the media, then add a "Case MediaType.NEWMEDIA" to the Select statement in the abstract factory class.

Resources

Data & Object Factory - Design Patterns: Abstract Factory
Wikipedia - Abstract factory pattern
DotNetExtreme - Abstract Factory Pattern

Wednesday, November 12, 2003

Software Design Patterns


Partly for my own education and partly to interest anyone who may be reading this blog, I'm going to do a series of posts on software design patterns. I find that describing something so another can understand it improves my own understanding, so I'll begin with the "Gang of Four" Factory Pattern.

Factory Pattern


Basic Description

A Factory is a class (or it can be just a method) that creates objects derived from a common super-class or interface. It is usually used in a situation where you don't want your client class to have to figure out what the specific class of an object is, because it could be of several different types. You create a super-class or interface and code the client to call methods of that super-class or interface. Now you have the problem of how to provide the different objects to the client without the client having to know which class is being created. The answer is to create a factory class that has a method that takes a parameter which it uses to figure out which type of object to return.

Example Code

Here is an example in VB.NET of a factory pattern:
(Note: If large spaces appear between lines of code then widen your browser)

First the factory class. (Note: this could be implemented as a method in the client class rather than as a class.)

Public Class ProcessControllerFactory

Public Shared Function GetController( process As String) As ProcessController
Dim result As ProcessController

Select Case process.ToUpper()
Case "EXTRACT"
result = New ExtractController()
Case "IMPORT"
result = New ImportController()
Case "MATCHING"
result = New MatchingController()
Case "CONFIRMATION"
result = New ConfirmationController()
Case "DISTRIBUTION"
result = New DistributionController()
Case Else
result = Nothing
End Select

Return result
End Function

End Class



The client class gets the process controller it wants like this:

Public Sub Execute( action as String)
'declare the variable using the superclass as the type
Dim processCtrl As ProcessController
'now get the controller
processCtrl = ProcessControllerFactory.GetController(action)
'now call the method common to all classes derived from the superclass
processCtrl.runProcesses()
'other code here
End Sub


If the factory were implemented as a method then "Execute" would look like this:

Public Sub Execute( action as String)
Dim processCtrl As ProcessController
'calls its own method
processCtrl = GetController(action)
processCtrl.runProcesses()
'other code here
End Sub


The classes of the objects produced by the factory look like this:

Public Class ImportController
Inherits ProcessController

Public Overrides Sub runProcesses()
'code goes here
End Sub

End Class


And the super-class of all process controller classes looks like this:

Public MustInherit Class ProcessController

Public Overridable Sub runProcesses()
'default handling code goes here or it could be an abstract method
End Sub

End Class

Resources

Factory pattern example
The Factory Method Design Pattern by Gopalan Suresh Raj
Solve application issues with the factory pattern
Implementing the factory pattern using attributes and activation - C# Programming
The Simple Factory Pattern in C#

Friday, November 07, 2003

Psychiatry USA


I just came across a site that gives the entire strategy used by psychiatry.

It also points out that no physical tests exist to show that any "mental disease" exists. One quote is from the mighty National Institute of Mental Health: "...there is no independent test for ADHD. This is not unique to ADHD, but applies as well to most psychiatric disorders, including other disabling disorders such as schizophrenia..." Click on this link for more quotes on the fact of no tests for mental disorders.

Tuesday, November 04, 2003

Cancellation of the Reagan mini-series


I'm not particularly political, it's not a sport I'm very interested in, I prefer sports like basketball or soccer. I am also not a fan nor a detractor of Ronald Reagan; I took even less interest in politics in the 80's than I do now. But when I heard some of the quotes from the script of "The Reagans" I was angered by this new method of character assassination and abuse of the freedom of speech.

I think the founding fathers must be spinning in their graves at the kind of abuse that passes for freedom of speech these days. Back when the US was founded they knew what freedom of speech meant because for years it had been denied them by a repressive imperial government. If you spoke out of line you ended up in jail or worse. Now we see things like pornography, pirating of copyrights and outright lies defended as "freedom of speech".

Want to know what freedom of speech really is? Then go to North Korea, Iran or China and start speaking out against those repressive regimes. You'll soon get the idea.

But perhaps there is hope for true freedom of speech. The public outcry against the Reagan mini-series was fueled in large part by such non-mainstream media outlets as the Drudge Report and talk radio. Thanks to the Internet, people were able to deluge CBS with complaints to the point where it became clear to the powers-that-be at CBS that this show was going to be a major embarrassment to them, so they pulled the plug.

Another good sign was something I heard on the radio this morning. It was on KNX 1070 in LA, which is a CBS radio station. A reporter was interviewing the TV critic of the LA Times. I thought, "here we go", CBS interviewing a guy from a very left-leaning paper. The outcome seemed obvious. But I was wrong. The interviewer was trying to characterize the pressure on CBS as coming from the famous "great right-wing conspiracy" that was dreamed up during the Clinton era, but the TV critic was having none of it and simply pointed out that a "docu-drama" that was full of lies shouldn't be aired in the first place and that the producers should have made sure it was truthful then no one could have complained about it.

And I think that is the essence of what freedom of speech is all about: TRUTH.

Monday, November 03, 2003

Another Good Blog


My friend Zack, who is studying at Berkley University, has a very interesting blog. He talks about history, science and philosophy in a very enlightening way. I've added a link to his site in my links - click on The Lab.