By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,361 Members | 3,185 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,361 IT Pros & Developers. It's quick & easy.

Polymorphism and inheritance patterns in VB

P: n/a
The classing Visual Basic and VBA support for polymorphism, let's face it, is
a bit on the weak side, and built-in support for inheritance is non-existent.
This little essay is about some patterns I've ended up using successfully for
certain kinds of inheritance and polymorphism, and some that have not worked
out so well.

Let's start with obvious things that turn out not to work well:
1. Use interface classes and "Implements" for polymorphism:

At first glance, this seems like a fine choice. After all, in languages like
Java, interface implementation is used by most programmers at least as often
as inheritance, and is better than inheritance for many things. Also, using
interfaces allows for polymorphism without breaking type safety. Alas, in VB
things are not as good as they at first appear.

As it turns out, interfaces and Implements are useful sometimes in limited
circumstances, but the way they work in VB makes them often take extra effort
to maintain and makes them behave unpredictably in many circumstances.
First of all, rather than simply requiring that all the interface members be
implemented and making them visible through the interface like Java would do,
VB requries you to explicitly create an implementation of each method for each
interface using a qualified name. Each of these is then a separate method
that can its own different implementation (oh what a tangled web that could
be), and to make all cases act the same (like you want about 100% of the
time), you must explicitly call one central method from each of the interface
implementations fo the case.

Now, if that weren't bad enough, you'd best be careful never to mix early
binding and late binding code on the same classes in the wrong order because
if you set an Object variable equal to a variable of an interface type, the
object behaves as an instance of the interface it was in before you assigned
it. In other words, even though it is now housed in an Object variable, you
can't access any members or attributes of the object other than the ones
exposed through the last interface it used as before it went -in- to the
Object variable. What a mess.
2. Using composition and delegation to simulate inheritance:

Since you can't have one class implicitly inherit from and extend another, the
next thing that comes to mind is to create an "inheriting" class that exposes
the same methods as and contains an instance of the parent class, then
forwards calls to the contained "parent" from any method that is not supposed
to override the parent behavior.

In practice, this is a seious hassle. If you use interfaces, the compiler
will tell you when a change to the parent necessitates a change to the
"inheriting" class, but with all the overhead of interfaces discussed above.
If you use late binding and no interfaces, then you don't have the hassle, but
you also don't have the compiler forcing you to update the inheriting classes
when a parent changes, and it can be a lot of effort tracking them down. As a
final blow, you can't inherit and override anything private to the "parent"
class.
Next, for some things that often do work well.

1. Using late binding for polymorphism:

Rather than using interfaces, you can simply allow code to use instances of
certain classes polymorhically by storing everything in a simple Object
variable.

This technique does have some notable down-sides, but the up-sides can often
outweigh it. The biggest down-side is that the compiler can't make sure that
only classes that follow a particular interface can be passed to procedures
that expect to use that interface. If it breaks, it will break at run-time.
The big up-side is that it doesn't require much code overhead at all.

If there's a part of your code that's really begging for a large number of
classes to be used interchangeably by some procedures, this may be a good way
to go. To mitigate the down-sides, try to make sure code that's written this
way will pass instances of every class that might be passed, and call
everything that might be called one each one early in testing. That way, if
you do break something, you'll know about it before you deploy it. If
necessary, write some automated tests as insurance, and run them before each
deployment.
2. Use inverted containership (I believe my way of doing this is a version of
the "Decorator Pattern").

In this pattern, you implement something resembling inheritance by having one
class that always acts as the interface layer, and its run-time behavior is
determined by what kind of class instance it is encapsulating at run-time. In
other words, you might "decorate" a clsQuery class by supplying it with an
instance of clsInvoiceLineQuerySpec. clsQuery provides the publicly
accessible interface, and clsInvoiceLineQuerySpec has method signatures
clsQuery understands that provide the clsQuery instance with specific data
constants and procedures that enable it to operate in a specific context (e.g.
a SQL string).

Note that in this case, it can be somewhat practical to use an "Interface" for
the specific classes to define what they must make available to the general
interface class. The specific classes might never need to be accessed any
other way than through that interface, so there are no ambiguities or wrapped
calls to worry about.

3. Instances as "classes":

In many cases, it is sufficient to customize the behavior of an object through
initialization data alone. In this case, you can have a public function that
initializes an object with the correct data, and returns it. A form of
inheritance can be implemented in this scheme by supplying each class with a
Clone procedure, so you can clone one and extend or modify its behavior to
handle a more specific case.

For instance, let's say I have a class clsQuery that gets all its behavior
from the values of members called ParametersClause, SelectList, FromClause,
WhereClause, GroupByClause, and HavingClause. Now, let's say you provide a
public function called InvoiceLineQuery that initializes a clsQuery instance
with SelectList = "tblInvoiceLines.*" and FromClause = "tblInvoices". Now,
you have an object that can query the entire tblInvoiceLines table.

Now, implement another function called InvoiceLinesForInvoice that calls
InvoiceLineQuery to get an instance, then sets ParametersClause =
"prmInvoiceId Long" and WhereClause =
"tblInvoiceLines.InvoiceId=prmInvoiceId". This instance can be used to query
just the lines for a particular invoice.

As you can see, this can be a reasonably useful sort of real inheritance.
Note that .NET does similar things with the WindowsForms model. Each
WindowsForm object is constructed at run-time, but the code structures that do
the construction allow for a sort of inheritance by sequential addition of
items to the form's collections. I believe this is another sort of
implementation of the "Decorator Pattern".
Nov 13 '05 #1
Share this Question
Share on Google+
12 Replies


P: n/a
Somehow, I can't seem to post anything to Usenet without suddenly finding a
glaring editing mistake right after posting it.
The classing Visual Basic and VBA support for polymorphism, let's face it, is
a bit on the weak side, and built-in support for inheritance is non-existent.


That should read...

The Visual Basic and VBA support for class polymorphism, let's face it, is a
bit on the weak side, and built-in support for inheritance is non-existent.

Nov 13 '05 #2

P: n/a
rkc
Steve Jorgensen wrote:
2. Use inverted containership (I believe my way of doing this is a version of
the "Decorator Pattern").

In this pattern, you implement something resembling inheritance by having one
class that always acts as the interface layer, and its run-time behavior is
determined by what kind of class instance it is encapsulating at run-time. In
other words, you might "decorate" a clsQuery class by supplying it with an
instance of clsInvoiceLineQuerySpec. clsQuery provides the publicly
accessible interface, and clsInvoiceLineQuerySpec has method signatures
clsQuery understands that provide the clsQuery instance with specific data
constants and procedures that enable it to operate in a specific context (e.g.
a SQL string).

Note that in this case, it can be somewhat practical to use an "Interface" for
the specific classes to define what they must make available to the general
interface class. The specific classes might never need to be accessed any
other way than through that interface, so there are no ambiguities or wrapped
calls to worry about.


Actually, you don't decorate an object by passing it an instance of
another object. You decorate an object by passing it to an instance
of the decorator object. Polymorphism (via an interface) is fundamental
to the pattern so that you can sequentially decorate the initial object
with any number of additional objects. When the defined method(s) are
called on the last decorator they are called last in first out on all
the contained objects.

It might be entertaining to build a query that way, but your #3 way of
simply building a class with all the necessary methods probably makes
more sense.


Nov 13 '05 #3

P: n/a
On Thu, 16 Dec 2004 02:12:53 GMT, rkc <rk*@rochester.yabba.dabba.do.rr.bomb>
wrote:
Steve Jorgensen wrote:
....
Actually, you don't decorate an object by passing it an instance of
another object. You decorate an object by passing it to an instance
of the decorator object. Polymorphism (via an interface) is fundamental
to the pattern so that you can sequentially decorate the initial object
with any number of additional objects. When the defined method(s) are
called on the last decorator they are called last in first out on all
the contained objects.
Regarding the Decorator Pattern, it sounds like I really don't get it. I'll
try to get more clear on that and also see if I can figure out what if any
existing named pattern my pattern actually resembles.
It might be entertaining to build a query that way, but your #3 way of
simply building a class with all the necessary methods probably makes
more sense.


I agree. Option 3 is what I normally use for query classes, and it works
really well. I have found option 2 to work well with reader/writer classes,
but the explanation of that is a bit lengthy.
Nov 13 '05 #4

P: n/a
On Thu, 16 Dec 2004 02:12:53 GMT, rkc <rk*@rochester.yabba.dabba.do.rr.bomb>
wrote:
Steve Jorgensen wrote:
2. Use inverted containership (I believe my way of doing this is a version of
the "Decorator Pattern").

In this pattern, you implement something resembling inheritance by having one
class that always acts as the interface layer, and its run-time behavior is
determined by what kind of class instance it is encapsulating at run-time. In
other words, you might "decorate" a clsQuery class by supplying it with an
instance of clsInvoiceLineQuerySpec. clsQuery provides the publicly
accessible interface, and clsInvoiceLineQuerySpec has method signatures
clsQuery understands that provide the clsQuery instance with specific data
constants and procedures that enable it to operate in a specific context (e.g.
a SQL string).

Note that in this case, it can be somewhat practical to use an "Interface" for
the specific classes to define what they must make available to the general
interface class. The specific classes might never need to be accessed any
other way than through that interface, so there are no ambiguities or wrapped
calls to worry about.


Actually, you don't decorate an object by passing it an instance of
another object. You decorate an object by passing it to an instance
of the decorator object. Polymorphism (via an interface) is fundamental
to the pattern so that you can sequentially decorate the initial object
with any number of additional objects. When the defined method(s) are
called on the last decorator they are called last in first out on all
the contained objects.


OK, I get it now. From what I can tell, the pattern I'm describing most
closely resembles the "Strategy Pattern".

http://www.exciton.cs.rice.edu/JavaR...egyPattern.htm

As for option 3, it seems to be most like the prototype pattern. I often use
a public function to make new "prototypes" rather than clone them from a true
prototype, but it's still pretty close.
http://www.c-sharpcorner.com/Languag...rnsinCSRVS.asp
Nov 13 '05 #5

P: n/a
Interesting Point

"Steve Jorgensen" <no****@nospam.nospam> wrote in message
news:7g********************************@4ax.com...
Somehow, I can't seem to post anything to Usenet without suddenly finding a glaring editing mistake right after posting it.
The classing Visual Basic and VBA support for polymorphism, let's face it, isa bit on the weak side, and built-in support for inheritance is
non-existent.
That should read...

The Visual Basic and VBA support for class polymorphism, let's face it, is a bit on the weak side, and built-in support for inheritance is non-existent.

Nov 13 '05 #6

P: n/a
interesting point

"Steve Jorgensen" <no****@nospam.nospam> wrote in message
news:h3********************************@4ax.com...
The classing Visual Basic and VBA support for polymorphism, let's face it, is a bit on the weak side, and built-in support for inheritance is non-existent. This little essay is about some patterns I've ended up using successfully for certain kinds of inheritance and polymorphism, and some that have not worked out so well.

Let's start with obvious things that turn out not to work well:
1. Use interface classes and "Implements" for polymorphism:

At first glance, this seems like a fine choice. After all, in languages like Java, interface implementation is used by most programmers at least as often as inheritance, and is better than inheritance for many things. Also, using interfaces allows for polymorphism without breaking type safety. Alas, in VB things are not as good as they at first appear.

As it turns out, interfaces and Implements are useful sometimes in limited
circumstances, but the way they work in VB makes them often take extra effort to maintain and makes them behave unpredictably in many circumstances.
First of all, rather than simply requiring that all the interface members be implemented and making them visible through the interface like Java would do, VB requries you to explicitly create an implementation of each method for each interface using a qualified name. Each of these is then a separate method
that can its own different implementation (oh what a tangled web that could be), and to make all cases act the same (like you want about 100% of the
time), you must explicitly call one central method from each of the interface implementations fo the case.

Now, if that weren't bad enough, you'd best be careful never to mix early
binding and late binding code on the same classes in the wrong order because if you set an Object variable equal to a variable of an interface type, the object behaves as an instance of the interface it was in before you assigned it. In other words, even though it is now housed in an Object variable, you can't access any members or attributes of the object other than the ones
exposed through the last interface it used as before it went -in- to the
Object variable. What a mess.
2. Using composition and delegation to simulate inheritance:

Since you can't have one class implicitly inherit from and extend another, the next thing that comes to mind is to create an "inheriting" class that exposes the same methods as and contains an instance of the parent class, then
forwards calls to the contained "parent" from any method that is not supposed to override the parent behavior.

In practice, this is a seious hassle. If you use interfaces, the compiler
will tell you when a change to the parent necessitates a change to the
"inheriting" class, but with all the overhead of interfaces discussed above. If you use late binding and no interfaces, then you don't have the hassle, but you also don't have the compiler forcing you to update the inheriting classes when a parent changes, and it can be a lot of effort tracking them down. As a final blow, you can't inherit and override anything private to the "parent" class.
Next, for some things that often do work well.

1. Using late binding for polymorphism:

Rather than using interfaces, you can simply allow code to use instances of certain classes polymorhically by storing everything in a simple Object
variable.

This technique does have some notable down-sides, but the up-sides can often outweigh it. The biggest down-side is that the compiler can't make sure that only classes that follow a particular interface can be passed to procedures that expect to use that interface. If it breaks, it will break at run-time. The big up-side is that it doesn't require much code overhead at all.

If there's a part of your code that's really begging for a large number of
classes to be used interchangeably by some procedures, this may be a good way to go. To mitigate the down-sides, try to make sure code that's written this way will pass instances of every class that might be passed, and call
everything that might be called one each one early in testing. That way, if you do break something, you'll know about it before you deploy it. If
necessary, write some automated tests as insurance, and run them before each deployment.
2. Use inverted containership (I believe my way of doing this is a version of the "Decorator Pattern").

In this pattern, you implement something resembling inheritance by having one class that always acts as the interface layer, and its run-time behavior is determined by what kind of class instance it is encapsulating at run-time. In other words, you might "decorate" a clsQuery class by supplying it with an
instance of clsInvoiceLineQuerySpec. clsQuery provides the publicly
accessible interface, and clsInvoiceLineQuerySpec has method signatures
clsQuery understands that provide the clsQuery instance with specific data
constants and procedures that enable it to operate in a specific context (e.g. a SQL string).

Note that in this case, it can be somewhat practical to use an "Interface" for the specific classes to define what they must make available to the general interface class. The specific classes might never need to be accessed any
other way than through that interface, so there are no ambiguities or wrapped calls to worry about.

3. Instances as "classes":

In many cases, it is sufficient to customize the behavior of an object through initialization data alone. In this case, you can have a public function that initializes an object with the correct data, and returns it. A form of
inheritance can be implemented in this scheme by supplying each class with a Clone procedure, so you can clone one and extend or modify its behavior to
handle a more specific case.

For instance, let's say I have a class clsQuery that gets all its behavior
from the values of members called ParametersClause, SelectList, FromClause, WhereClause, GroupByClause, and HavingClause. Now, let's say you provide a public function called InvoiceLineQuery that initializes a clsQuery instance with SelectList = "tblInvoiceLines.*" and FromClause = "tblInvoices". Now, you have an object that can query the entire tblInvoiceLines table.

Now, implement another function called InvoiceLinesForInvoice that calls
InvoiceLineQuery to get an instance, then sets ParametersClause =
"prmInvoiceId Long" and WhereClause =
"tblInvoiceLines.InvoiceId=prmInvoiceId". This instance can be used to query just the lines for a particular invoice.

As you can see, this can be a reasonably useful sort of real inheritance.
Note that .NET does similar things with the WindowsForms model. Each
WindowsForm object is constructed at run-time, but the code structures that do the construction allow for a sort of inheritance by sequential addition of
items to the form's collections. I believe this is another sort of
implementation of the "Decorator Pattern".

Nov 13 '05 #7

P: n/a

Steve Jorgensen wrote:
On Thu, 16 Dec 2004 02:12:53 GMT, rkc <rk*@rochester.yabba.dabba.do.rr.bomb> wrote: OK, I get it now. From what I can tell, the pattern I'm describing most closely resembles the "Strategy Pattern".

http://www.exciton.cs.rice.edu/JavaR...egyPattern.htm

I really like this idea. Can you post code for a small example?
Thanks,
JAF

Nov 13 '05 #8

P: n/a
I found this thread interesting and thought I would share my humble 2
cents worth in exchange for a general question about .Net that I have
which is slightly related to this topic for which I have not found an
answer.

As for simulating OOP stuff with vb6 and vba, the best I was able to
come up with that was somewhat reliable was overloading - by creating a
class object and send the same named object any variety of arguments
where the class contains a variety of methods for various args - kind of
like reiventing the wheel in an OOP language where the same thing is
done for you under the hood. I do this overloading thing in Access
quite frequently because this way I can call a variety of methods with
the same name (overloading) in a loop. And a plug for vb.net, I use
Interfaces and delegate frequently (well, maybe not delegates so much -
function pointers) and I have not had any issues in vb.net. For OOP
languages, vb (vb.net) still maintains the lead in ease of use and
development speed and is almost as sophisticated as C# and Java. I
noticed that C# and Java don't have as much intellisense as vb.net. I
have had to start using C# on more and more projects, and when I can't
figure out a syntax, I write the equivalent code in a test vb.net app
and look at the intellisense. In Java, well, I write Java only when I
really have to (for Lotus Notes). So here is my general question about
OOP and dotnet.

In vb6 I have developed several ActiveX.exe apps so that I can use
CreateObject and GetObject, the same as Access, Excel, Word. I have not
yet found a way to create the equivalent of an ActiveX.exe app in dotnet
and no one is talking about such a thing. So would anyone know if there
is such a thing in dotnet that is equivalent to the Com ActiveX.exe? If
not, is there a way for dotnet apps to interact with each other like Com
ActiveX.exe apps (Access, Excel, Word, etc)?

Rich

*** Sent via Developersdex http://www.developersdex.com ***
Don't just participate in USENET...get rewarded for it!
Nov 13 '05 #9

P: n/a
rkc
ji********@compumarc.com wrote:
http://www.exciton.cs.rice.edu/JavaR...egyPattern.htm

I really like this idea. Can you post code for a small example?


Here's a small and basically useless example of a Strategy pattern.
I think it does show pretty clearly how it works though.

<TestStrategy type="client code">
Public Sub TestStrategy()
Dim c As clsContext
Dim qryStrat As IQueryStrategy
Set c = New clsContext
Set qryStrat = New clsDLookupStrategy

qryStrat.build "Employees", "LastName", "EmployeeID = 1"
c.setStrategy qryStrat
MsgBox c.result

Set qryStrat = Nothing
Set c = Nothing

End Sub
</TestStrategy>

<IQueryStrategy type="Interface">
Private domain As String
Private expression As String
Private criteria As String

Public Sub build(sDomain As String, sExpression As String, sCriteria As
String)
'method body
End Sub

Public Function execute() As String
'method body
End Function
</IQueryStrategy>

<clsDLookupStrategy>
Implements IQueryStrategy
Private domain As String
Private expression As String
Private criteria As String
Private Sub IQueryStrategy_build(sDomain As String, sExpression As
String, sCriteria As String)
domain = sDomain
expression = sExpression
criteria = sCriteria
End Sub

Private Function IQueryStrategy_execute() As String
Dim s As String
s = DLookup(expression, domain, criteria)
IQueryStrategy_execute = "" & s
End Function
</clsDLookupStrategy>

<clsSqlStrategy>
Implements IQueryStrategy
Private domain As String
Private expression As String
Private criteria As String
Private Sub IQueryStrategy_build(sDomain As String, sExpression As
String, sCriteria As String)
domain = sDomain
expression = sExpression
criteria = sCriteria
End Sub

Private Function IQueryStrategy_execute() As String
Dim rs As DAO.Recordset
Dim s As String
Dim sql As String
sql = "SELECT " & expression & _
" FROM " & domain & _
" WHERE " & criteria

Set rs = CurrentDb.OpenRecordset(sql)

With rs
If Not .EOF Then
s = .Fields(0)
End If
.Close
End With

Set rs = Nothing

IQueryStrategy_execute = "" & s
End Function
</clsSqlStrategy>

<clsContext>
Private qry As IQueryStrategy

Public Sub setStrategy(stgy As IQueryStrategy)
Set qry = stgy
End Sub

Public Function result() As String
result = qry.execute
End Function
</clsContext>
Nov 13 '05 #10

P: n/a
Hi Jim,

....
http://www.exciton.cs.rice.edu/JavaR...egyPattern.htm

I really like this idea. Can you post code for a small example?
Thanks,
JAF
I finally got time to make up a little example for ya in addition to the one
RKC posted. This is not air code - it's tested and it works, though it is
obviously missing some error handling it would need for use in a production
app.

=== Module: basTestLogWriter
Option Compare Database
Option Explicit

Public Sub TestTxtFileLogWriter()
Dim objWriterStrategy As New clsLogWriterTxtFileStrategy

objWriterStrategy.FilePath = CurrentProject.Path & "\" & _
"LogWriterTest.txt"

WriteLogData objWriterStrategy

End Sub

Public Sub TestTableLogWriter()
Dim objWriterStrategy As New clsLogWriterTableStategy

With objWriterStrategy
.DbFilePath = CurrentProject.Path & "\" & _
"Log Writer Test Output.mdb"
.TableName = "tblLogEntry"
.FieldName = "LogEntryText"
End With

WriteLogData objWriterStrategy

End Sub

Private Sub WriteLogData(WriterStrategy As ILogWriterStrategy)
Dim objWriter As New clsLogWriter

objWriter.Setup WriterStrategy
objWriter.OpenLog

With objWriter
.WriteMessage "Test message 1"
.WriteMessage "Test message 2"
End With

objWriter.CloseLog

End Sub

=== Module: clsLogWriter
Option Compare Database
Option Explicit

Private mobjStrategy As ILogWriterStrategy

Public Sub Setup(Strategy As ILogWriterStrategy)
Set mobjStrategy = Strategy
End Sub

Public Property Get Strategy() As ILogWriterStrategy
Set Strategy = mobjStrategy
End Property

Public Sub OpenLog()
Strategy.OpenLog
End Sub

Public Sub CloseLog()
Strategy.CloseLog
End Sub

Public Sub WriteMessage(Message As String)
Dim strFormattedMsg As String

strFormattedMsg = FormatMessage(Message)
Strategy.WriteFormattedMsg strFormattedMsg

End Sub

Private Function FormatMessage(Message As String) As String
Const cstrTimestampFormat = "yyyy-mmm-dd hh:nn a/p"
Dim strTimestamp As String

strTimestamp = Format(Now, cstrTimestampFormat)
FormatMessage = BulletChar & " " & _
strTimestamp & ": " & _
Message
End Function

Private Function BulletChar() As String
BulletChar = Chr$(149)
End Function

=== Module: ILogWriterStrategy
Option Compare Database
Option Explicit

Public Sub OpenLog()
End Sub

Public Sub CloseLog()
End Sub

Public Sub WriteFormattedMsg(Message As String)
End Sub

=== Module: clsLogWriterTxtFileStrategy
Option Compare Database
Option Explicit

Implements ILogWriterStrategy

Public FilePath As String

Private mintFileNum As Integer

Public Sub ILogWriterStrategy_OpenLog()
mintFileNum = FreeFile
Open FilePath For Output As mintFileNum
End Sub

Public Sub ILogWriterStrategy_CloseLog()
Close mintFileNum
End Sub

Public Sub ILogWriterStrategy_WriteFormattedMsg( _
Message As String _
)
Print #mintFileNum, Message
End Sub

=== Module: clsLogWriterTableStategy
Option Compare Database
Option Explicit

Implements ILogWriterStrategy

Public DbFilePath As String
Public TableName As String
Public FieldName As String

Private mdbsLogDb As DAO.Database
Private mrstLogTable As DAO.Recordset

Public Sub ILogWriterStrategy_OpenLog()
Set mdbsLogDb = Workspaces(0).OpenDatabase(DbFilePath)
Set mrstLogTable = mdbsLogDb.OpenRecordset(TableName, _
dbOpenDynaset, _
dbAppendOnly)
End Sub

Public Sub ILogWriterStrategy_CloseLog()
mrstLogTable.Close
mdbsLogDb.Close
End Sub

Public Sub ILogWriterStrategy_WriteFormattedMsg( _
Message As String _
)
mrstLogTable.AddNew
mrstLogTable(FieldName) = Message
mrstLogTable.Update
End Sub
On 16 Dec 2004 10:32:46 -0800, ji********@compumarc.com wrote:

Steve Jorgensen wrote:
On Thu, 16 Dec 2004 02:12:53 GMT, rkc

<rk*@rochester.yabba.dabba.do.rr.bomb>
wrote:

OK, I get it now. From what I can tell, the pattern I'm describing

most
closely resembles the "Strategy Pattern".

http://www.exciton.cs.rice.edu/JavaR...egyPattern.htm

I really like this idea. Can you post code for a small example?
Thanks,
JAF


Nov 13 '05 #11

P: n/a
rkc
Steve Jorgensen wrote:
Hi Jim,

...
http://www.exciton.cs.rice.edu/JavaR...egyPattern.htm

I really like this idea. Can you post code for a small example?
Thanks,
JAF

I finally got time to make up a little example for ya in addition to the one
RKC posted. This is not air code - it's tested and it works, though it is
obviously missing some error handling it would need for use in a production
app.


Usefull example. It's pretty clear how it could be easily extended to
write to an XML file, another database or even an spreadsheet.
You also got the handling of the data in the context class
(clsLogWriter)where it belongs. I got that wrong. Not sure why you
expose Private mobjStrategy with a property get though.

The file setup code in the test module is ugly, but then I realized
in real life you would probably handle that in the strategy classes
via config data stored outside the application code.


Nov 13 '05 #12

P: n/a
On Mon, 20 Dec 2004 01:06:06 GMT, rkc <rk*@rochester.yabba.dabba.do.rr.bomb>
wrote:
Steve Jorgensen wrote:
Hi Jim,

...
http://www.exciton.cs.rice.edu/JavaR...egyPattern.htm

I really like this idea. Can you post code for a small example?
Thanks,
JAF

I finally got time to make up a little example for ya in addition to the one
RKC posted. This is not air code - it's tested and it works, though it is
obviously missing some error handling it would need for use in a production
app.


Usefull example. It's pretty clear how it could be easily extended to
write to an XML file, another database or even an spreadsheet.
You also got the handling of the data in the context class
(clsLogWriter)where it belongs. I got that wrong. Not sure why you
expose Private mobjStrategy with a property get though.


That was a case of "I needed it last time, so..." Frankly, I don't remember
why I need a public Strategy member, so I probably should have left it out
until the need arises again.
The file setup code in the test module is ugly, but then I realized
in real life you would probably handle that in the strategy classes
via config data stored outside the application code.


Pretty much, yeah. This was the minumum code I thought I could write that
would fully demonstrate the template pattern, and why it would be useful.

Nov 13 '05 #13

This discussion thread is closed

Replies have been disabled for this discussion.