<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Lotushints &#187; design patterns</title>
	<atom:link href="http://www.lotushints.com/category/design-patterns/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.lotushints.com</link>
	<description>Lotus Notes tips &#38; tricks you always hoped you will not need</description>
	<lastBuildDate>Thu, 29 Dec 2011 09:47:10 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Design patterns &#8211; Part 11: Bridge pattern</title>
		<link>http://www.lotushints.com/2009/06/design-patterns-part-11-bridge-pattern/</link>
		<comments>http://www.lotushints.com/2009/06/design-patterns-part-11-bridge-pattern/#comments</comments>
		<pubDate>Mon, 01 Jun 2009 07:00:38 +0000</pubDate>
		<dc:creator>Vladimir Kocjancic</dc:creator>
				<category><![CDATA[Best practices]]></category>
		<category><![CDATA[Code optimization]]></category>
		<category><![CDATA[design patterns]]></category>
		<category><![CDATA[bridge]]></category>
		<category><![CDATA[custom classes]]></category>
		<category><![CDATA[Lotus Notes]]></category>
		<category><![CDATA[object-oriented]]></category>
		<category><![CDATA[Object-oriented development]]></category>
		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://www.lotushints.com/?p=361</guid>
		<description><![CDATA[In part 11 of Design pattern series we will go into creating and using the Bridge design pattern. It is moderately used and uses encapsulation, inheritance and aggregation to separate responsibilities into other classes. The Bridge pattern decouples an abstraction from its implementation so that the two can vary independently. Usage The pattern is most [...]]]></description>
			<content:encoded><![CDATA[<p>In part 11 of <a href="../category/design-patterns/">Design pattern series</a> we will go into creating and using the Bridge design pattern. It is moderately used and uses encapsulation, inheritance and aggregation to separate responsibilities into other classes.</p>
<blockquote><p><strong>The Bridge pattern</strong> decouples an abstraction from its implementation so that the two can vary independently.</p></blockquote>
<p><span id="more-361"></span></p>
<p><strong>Usage</strong></p>
<p>The pattern is most useful, when both classes (implementation and abstraction) are assigned to different task handling. In our example, we will look at how to separate data and actions to build a list of products and navigate it.</p>
<p><strong>Data representation class</strong></p>
<p>This is an abstract class with only navigational methods specified. Data representation class must implement navigational logic in its methods and thus assures that no other class will change or handle any properties without data representation class knowledge.</p>
<p>Also, for needs of our example, we will also define a type that will contain product id, name and price.</p>
<pre>Type TBridgeData
   strId As String
   strName As String
   dPrice As Double
End Type

Class CBridgeDataObject
   Sub NextRecord ()
   End Sub

   Sub PrevRecord ()
   End Sub

   Sub AddRecord (strId As String, strName As String,_
   dPrice As Double)
   End Sub

   Sub RemoveRecord (strId As String )
   End Sub

   Sub ShowRecord ()
   End Sub

   Function ShowAllRecords () As String
   End Function
End Class</pre>
<p><strong>Product data class</strong></p>
<p>Class itself inherits from Data representation abstract class. Also, it contains all navigational logic as well as data handling.</p>
<p>Beware that for this example, I did not actually load the data from the database. Instead I created five (5) products in the class construct. In real life, you should have read the data from your database!</p>
<pre>Class CBridgeProductData As CBridgeDataObject
   Private m_nCurrent As Integer
   Private m_AProducts () As TBridgeData

   Sub New ()
      m_ncurrent = 0

      Redim m_AProducts(4)

      m_AProducts(0).strId = "PR-0001"
      m_AProducts(0).strName = "Product 1"
      m_AProducts(0).dPrice = 100.00

      m_AProducts(1).strId = "PR-0002"
      m_AProducts(1).strName = "Product 2"
      m_AProducts(1).dPrice = 1000.00

      m_AProducts(2).strId = "PR-0003"
      m_AProducts(2).strName = "Product 3"
      m_AProducts(2).dPrice = 150.00

      m_AProducts(3).strId = "PR-0004"
      m_AProducts(3).strName = "Product 4"
      m_AProducts(3).dPrice = 400.00

      m_AProducts(4).strId = "PR-0005"
      m_AProducts(4).strName = "Product 5"
      m_AProducts(4).dPrice = 330.00
   End Sub

   Sub NextRecord ()
      If (m_nCurrent < Ubound (m_AProducts)) Then
         m_nCurrent = m_nCurrent + 1
      End If
   End Sub

   Sub PrevRecord ()
      If (m_nCurrent > 0) Then
         m_nCurrent = m_nCurrent - 1
      End If
   End Sub

   Sub AddRecord (strId As String, strName As String,_
   dPrice As Double)
      Dim n As Integer

      n = Ubound (m_AProducts) + 1
      Redim Preserve m_AProducts (n)

      m_AProducts(n).strId = strId
      m_AProducts(n).strName = strName
      m_AProducts(n).dPrice = dPrice
   End Sub

   Sub RemoveRecord (strId As String)
      Dim n As Integer
      Dim m As Integer
      Dim nCount As Integer
      Dim nIndex As Integer

      m = 0
      nIndex = -1
      nCount = Ubound (m_AProducts)
      For n = 0 To nCount
         If (m_AProducts (n).strId <> strId) Then
            m_AProducts (m).strId = m_AProducts (n).strId
            m_AProducts (m).strName = m_AProducts (n).strName
            m_AProducts (m).dPrice = m_AProducts (n).dPrice
            m = m + 1
         Else
            nIndex = n
         End If
      Next

      Redim Preserve m_AProducts (nCount - 1)
      If (m_nCurrent > n) Then Call Me.PrevRecord ()
   End Sub

   Sub ShowRecord ()
      Dim strDisplay As String

      strDisplay = m_AProducts (m_nCurrent).strId &#038; { } &#038;_
      m_AProducts (m_nCurrent).strName &#038; { €} &#038;_
      m_AProducts (m_nCurrent).dPrice

      Messagebox strDisplay
   End Sub

   Function ShowAllRecords() As String
      Dim n As Integer
      Dim strDisplay As String

      strDisplay = ""
      For n = 0 To Ubound (m_AProducts)
         strDisplay = strDisplay &#038; Chr(13) &#038;_
         m_AProducts (n).strId &#038; { } &#038;_
         m_AProducts (n).strName &#038; { €} &#038;_
         m_AProducts (n).dPrice
      Next

      ShowAllRecords = strDisplay
   End Function
End Class</pre>
<p><strong>Product base class</strong></p>
<p>Now, that we have our data classes created, we need to build an abstraction class that will call actual navigation and display the list contents or item if necessary. As we might have multiple classes that should have same functionality, it is a must to create a base class first. This class will encapsulate Data representation abstract class.</p>
<pre>Class CBridgeProductBase
   Private m_DataObj As CBridgeDataObject
   Private m_strGroup As String

   Public Property Get Data
      Set Data = m_DataObj
   End Property

   Public Property Set Data
      Set m_DataObj = Data
   End Property

   Sub New (strGroup As String)
      m_strGroup = strGroup
   End Sub

   Sub Next ()
      Call m_DataObj.NextRecord ()
   End Sub

   Sub Prev ()
      Call m_DataObj.PrevRecord ()
   End Sub

   Sub Add (strId As String, strName As String, dPrice As Double)
      Call m_DataObj.AddRecord (strId, strName, dPrice)
   End Sub

   Sub Remove (strId As String)
      Call m_DataObj.RemoveRecord (strId)
   End Sub

   Sub Show ()
      Call m_DataObj.ShowRecord()
   End Sub

   Sub ShowAll ()
      Messagebox "Product group: " &#038; m_strGroup &#038; Chr (13) &#038;_
      m_DataObj.ShowAllRecords()
   End Sub
End Class</pre>
<p><strong>Concrete product class</strong></p>
<p>Concrete product class in our case, will only be used to alter presentation when ShowAll method is called. This is not a must.</p>
<pre>Class CBridgeProducts As CBridgeProductBase
   Sub New (strGroup As String)
   End Sub

   Sub ShowAll ()
      Messagebox "Displaying all products"
      Call CBridgeProductBase..ShowAll ()
   End Sub
End Class</pre>
<p><strong>Implementation</strong></p>
<p>For test purposes, I have created an agent that will:</p>
<ul>
<li>create product list</li>
<li>navigate forward and backward</li>
<li>add an item to the list</li>
<li>remove an item from the list</li>
<li>display single product or all products at any time,</li>
</ul>
<pre>Sub Initialize
   Dim products As CBridgeProducts
   Dim data As CBridgeProductData

   Set products = New CBridgeProducts ("product group 1")
   Set products.Data = New CBridgeProductData ()

   Call products.Show ()
   Call products.Next ()
   Call products.Show ()
   Call products.Prev ()
   Call products.Show ()
   Call products.ShowAll ()

   Call products.Add ("PR-0010", "New product", 1475.00)
   Call products.ShowAll ()
   Call products.Remove ("PR-0004")
   Call products.ShowAll ()
End Sub</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.lotushints.com/2009/06/design-patterns-part-11-bridge-pattern/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Design patterns &#8211; Part 10: Builder pattern</title>
		<link>http://www.lotushints.com/2009/05/design-patterns-part-10-builder-pattern/</link>
		<comments>http://www.lotushints.com/2009/05/design-patterns-part-10-builder-pattern/#comments</comments>
		<pubDate>Mon, 18 May 2009 06:00:47 +0000</pubDate>
		<dc:creator>Vladimir Kocjancic</dc:creator>
				<category><![CDATA[Basic]]></category>
		<category><![CDATA[Best practices]]></category>
		<category><![CDATA[Code optimization]]></category>
		<category><![CDATA[design patterns]]></category>
		<category><![CDATA[Intermediate]]></category>
		<category><![CDATA[Lotus Domino]]></category>
		<category><![CDATA[Object-oriented development]]></category>
		<category><![CDATA[absract factory]]></category>
		<category><![CDATA[builder]]></category>
		<category><![CDATA[custom classes]]></category>
		<category><![CDATA[LotusScript]]></category>
		<category><![CDATA[maintenance]]></category>
		<category><![CDATA[object-oriented]]></category>

		<guid isPermaLink="false">http://www.lotushints.com/?p=349</guid>
		<description><![CDATA[In part 10 of Design pattern series we will take look at Builder design pattern. Albeit much similarity, this pattern it is not to be mistaken with Abstract factory pattern. As Abstract Factory emphasizes a family of products and returns the product immediately, Builder focuses on constructing complex object step by step, returning product in [...]]]></description>
			<content:encoded><![CDATA[<p>In part 10 of <a href="/category/design-patterns/">Design pattern series</a> we will take look at Builder design pattern. Albeit much similarity, this pattern it is not to be mistaken with Abstract factory pattern. As Abstract Factory emphasizes a family of products and returns the product immediately, Builder focuses on constructing complex object step by step, returning product in final step.</p>
<blockquote><p>The intention of the <strong>The Builder pattern</strong> is to abstract steps of construction of objects so that different implementations of these steps can construct different representations of objects.</p></blockquote>
<p><span id="more-349"></span></p>
<p><strong>Huh?</strong></p>
<p>The best way to explain how builder pattern works is to look at the example. Imagine you have to build product presentation for a company that sells built PCs. For clarity&#8217;s sake, let&#8217;s pretend that they sell only two types of computers. One for basic office needs, running Linux OS and one for pro gaming needs running Windows.</p>
<p><strong>Let&#8217;s go!</strong></p>
<p>First, you need a product class. This class will be able to store product type, add components and display itself when needed. This allows you to build product with as many components as needed.</p>
<pre>Class CBuilderProduct
	Private m_strProductName As String
	Private m_strLParts List As String

	Sub New (productName As String)
		m_strProductName = productName
	End Sub

	Sub Add (part As String, desc As String)
		m_strLParts (part) = desc
	End Sub

	Sub Show ()
		Dim strDisplay As String

		strDisplay = "Product: " &amp; m_strProductName
		Forall part In m_strLParts
			strDisplay = strDisplay &amp; Chr(13) &amp;_
                      Listtag (part) &amp; ": " &amp; part
		End Forall
		Messagebox strDisplay
	End Sub
End Class</pre>
<p>Next, you need a builder class. This is an abstract class, only specifying methods and variables used by end product classes that inherit from it.</p>
<pre>Class CBuilder
	Private m_Product As CBuilderProduct

	Property Get Product As CBuilderProduct
		Set Product = m_Product
	End Property

	Sub AddOS()
	End Sub

	Sub AddPC()
	End Sub
End Class</pre>
<p>Now, you are ready to create real product classes. In our case, this classes will represent Basic and Pro products.</p>
<pre>Class CBuilderProductBasic As CBuilder
   Sub New()
      Set m_Product = New CBuilderProduct ("Basic Package")
   End Sub

   Sub AddOS()
      Call m_Product.Add ("Operating system", "Fedora Core 10")
   End Sub

   Sub AddPC()
      Call m_Product.Add ("Computer", "Basic home computer")
   End Sub
End Class

Class CBuilderProductPro As CBuilder
   Sub New()
      Set m_Product = New CBuilderProduct ("Pro Package")
   End Sub

   Sub AddOS()
      Call m_Product.Add ("Operating system", "Windows 7")
   End Sub

   Sub AddPC()
      Call m_Product.Add ("Computer", "Pro gaming computer")
   End Sub
End Class</pre>
<p>You are almost done. But first, you need a catalogue (or shop) class. This class will actually contain algorithm for building desired products. Beware that<em> builder</em> parameter of <em>Create </em>method must be of type <em>Variant </em>(it should be <em>CBuilder</em>) or you will get an error while compiling your code that will use this design pattern!</p>
<pre>Class CBuilderCatalog
	Sub Create (builder As Variant)
		Call builder.AddPC()
		Call builder.AddOS()
	End Sub
End Class</pre>
<p>To test the code, I wrote a simple agent that simply outputs two message boxes. One for each product.</p>
<pre>Sub Initialize
	Dim builder As CBuilder
	Dim shop As CBuilderCatalog

	Set shop = New CBuilderCatalog ()

	Set builder = New CBuilderProductBasic ()
	Call shop.Create (builder)
	Call builder.Product.Show()

	Set builder = New CBuilderProductPro ()
	Call shop.Create (builder)
	Call builder.Product.Show()
End Sub</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.lotushints.com/2009/05/design-patterns-part-10-builder-pattern/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Design patterns &#8211; Part 9: Mediator pattern</title>
		<link>http://www.lotushints.com/2009/04/design-patterns-part-9-mediator-pattern/</link>
		<comments>http://www.lotushints.com/2009/04/design-patterns-part-9-mediator-pattern/#comments</comments>
		<pubDate>Mon, 20 Apr 2009 08:00:28 +0000</pubDate>
		<dc:creator>Vladimir Kocjancic</dc:creator>
				<category><![CDATA[Best practices]]></category>
		<category><![CDATA[Code optimization]]></category>
		<category><![CDATA[design patterns]]></category>
		<category><![CDATA[Intermediate]]></category>
		<category><![CDATA[Lotus Domino]]></category>
		<category><![CDATA[Object-oriented development]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[custom classes]]></category>
		<category><![CDATA[LotusScript]]></category>
		<category><![CDATA[maintenance]]></category>
		<category><![CDATA[mediator]]></category>
		<category><![CDATA[object-oriented]]></category>

		<guid isPermaLink="false">http://www.lotushints.com/?p=320</guid>
		<description><![CDATA[This week, I present to you not much used, but quite useful Mediator pattern. Mediator pattern provides a unified interface to set of interfaces in a subsystem. Or, to simplify&#8230; Mediator pattern is mediator for communication between several classes. Example Now, the easiest way to explain this pattern is via example. Example itself is borrowed [...]]]></description>
			<content:encoded><![CDATA[<p>This week, I present to you not much used, but quite useful Mediator pattern.</p>
<blockquote><p><strong>Mediator pattern</strong> provides a unified interface to set of interfaces in a subsystem.</p></blockquote>
<p>Or, to simplify&#8230; Mediator pattern is mediator for communication between several classes.</p>
<p><span id="more-320"></span></p>
<p><strong>Example</strong></p>
<p>Now, the easiest way to explain this pattern is via example. Example itself is borrowed from <a href="http://www.dofactory.com/Patterns/PatternMediator.aspx" target="_blank">dofactory page</a>, but modified to fit LotusScript. It is about a simple support chat room. This chat room has several users of two types: admins and customers. I will call them participants. These participants can communicate amongst each other, presuming, they know user ids.</p>
<p>First, we need a chatroom template class, as we might end up with more than one chat room. Chat room will need to register participants and to be able to deliver messages to them.</p>
<pre>Class CChatroomTemplate
   Sub Register (participant As CParticipant)
   End Sub

   Sub Send (strFrom As String, strTo As String, strMsg As String)
   End Sub
End Class</pre>
<p>As participants need instance of chatroom class and chatroom needs list of participant class instances, we need to create chatroom and participant class frameworks and only then put code into it. Participants need to be able to send and receive messages. Finished classes are displayed below.</p>
<pre>Class CSupportChat As CChatroomTemplate
   m_LMembers List As CParticipant

   Sub Register(participant As CParticipant)
      If (Not Iselement (m_LMembers (participant.UserId))) Then
         Set m_LMembers (participant.UserId) = participant
      End If
      Set participant.Chatroom = Me
   End Sub

   Sub Send (strFrom As String, strTo As String, strMsg As String)
      Dim participant As CParticipant

      If (Not Iselement (m_LMembers (strTo))) Then Exit Sub
      Set participant = m_LMembers (strTo)
      Call participant.Receive (strFrom, strMsg)
   End Sub
End Class

Class CParticipant
   m_chatroom As CSupportChat
   m_strUserId As String

   Property Set Chatroom As CSupportChat
      Set m_chatroom = Chatroom
   End Property

   Property Get UserId As String
      UserId = m_strUserId
   End Property

   Property Set UserId As String
      m_strUserId = UserId
   End Property

   Sub new (strUserId As String)
      m_strUserId = strUserId
   End Sub

   Sub Send (strTo As String, strMsg As String)
      Call m_chatroom.Send (m_strUserId, strTo, strMsg)
   End Sub

   Sub Receive (strFrom As String, strMsg As String)
      Messagebox strFrom &amp; " to " &amp; m_strUserId &amp; ": " &amp; strMsg
   End Sub
End Class</pre>
<p>Now that base classes are set, it is time to create real participant classes. In our case, we need one for admins and one for regular users.</p>
<pre>Class CAdmin As CParticipant
   Sub new (strUserId As String)
   End Sub

   Sub Receive (strFrom As String, strMsg As String)
      Messagebox "Admin message"
      Call CParticipant..Receive (strFrom, strMsg)
   End Sub
End Class

Class CUser As CParticipant
   Sub new (strUserId As String)
   End Sub

   Sub Receive (strFrom As String, strMsg As String)
      Messagebox "User message"
      Call CParticipant..Receive (strFrom, strMsg)
   End Sub
End Class</pre>
<p><strong>Testing the code</strong></p>
<p>For testing purposes, I put it all in agent, created four users (of which one is admin) and sent 3 messages to admin and admin responded to first one. The code is below.</p>
<pre>Sub Initialize
   Dim chatroom As CSupportChat
   Dim user1 As CParticipant
   Dim user2 As CParticipant
   Dim user3 As CParticipant
   Dim user4 As CParticipant

   Set chatroom = New CSupportChat()
   Set user1 = New CUser ("User 1")
   Set user2 = New CUser ("User 2")
   Set user3 = New CUser ("User 3")
   Set user4 = New CAdmin ("Admin 1")

   Call chatroom.Register (user1)
   Call chatroom.Register (user2)
   Call chatroom.Register (user3)
   Call chatroom.Register (user4)

   Call user1.Send ("Admin 1", "Help?")
   Call user4.Send ("User 1", "What's wrong?")
   Call user2.Send ("Admin 1", "My server just crashed!!!")
   Call user3.Send ("Admin 1", "Network died!")
End Sub</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.lotushints.com/2009/04/design-patterns-part-9-mediator-pattern/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Design patterns &#8211; Part 8: State pattern</title>
		<link>http://www.lotushints.com/2009/03/design-patterns-part-8-state-pattern/</link>
		<comments>http://www.lotushints.com/2009/03/design-patterns-part-8-state-pattern/#comments</comments>
		<pubDate>Mon, 09 Mar 2009 08:00:35 +0000</pubDate>
		<dc:creator>Vladimir Kocjancic</dc:creator>
				<category><![CDATA[Best practices]]></category>
		<category><![CDATA[Code optimization]]></category>
		<category><![CDATA[design patterns]]></category>
		<category><![CDATA[Intermediate]]></category>
		<category><![CDATA[Lotus Domino]]></category>
		<category><![CDATA[Object-oriented development]]></category>
		<category><![CDATA[custom classes]]></category>
		<category><![CDATA[LotusScript]]></category>
		<category><![CDATA[maintenance]]></category>
		<category><![CDATA[object-oriented]]></category>
		<category><![CDATA[state]]></category>

		<guid isPermaLink="false">http://www.lotushints.com/?p=234</guid>
		<description><![CDATA[State pattern is probably most used in review cycles. The definition says: State pattern allows an object to appear as it can change its class by altering its behaviour and state. What are you talking about? Well, imagine you are in need to build a bug tracking database.  Bug reports in basics have four states. [...]]]></description>
			<content:encoded><![CDATA[<p>State pattern is probably most used in review cycles. The definition says:</p>
<blockquote><p><strong>State pattern</strong> allows an object to appear as it can change its class by altering its behaviour and state.</p></blockquote>
<p><strong>What are you talking about?</strong></p>
<p>Well, imagine you are in need to build a bug tracking database.  Bug reports in basics have four states. First they are <strong>unassigned</strong> until someone is solving them. When they are taken over, they become <strong>assigned</strong>, specifying that someone is already working on them. After bug fix has been produced, it is a good practice to <strong>send </strong>it<strong> to testing</strong>. Then it is up to QA to confirm that bug fix is <strong>complete </strong>or whether it is not.</p>
<p><span id="more-234"></span></p>
<p><strong>Show me the code!</strong></p>
<p>Example will be based on simple bug report specified above. However, I will skip actual action implementation as it varies based on application needs. Instead, I will use message box to print out the action report.</p>
<p>So, now, first what you need is a state abstract class that will implement all methods needed for transition between states (in our case: unassigned, assigned, send to testing and complete).</p>
<pre>Class CState
	Sub TakeOver()
	End Sub

	Sub SendToTesting()
	End Sub

	Sub Complete()
	End Sub
End Class</pre>
<p>Then, what you need is a context class that will be used when changing state of a bug report.</p>
<pre>Class CStateBugReport
   stateUnassigned As CState
   stateAssigned As CState
   stateReadyForTesting As CState
   stateCompleted As CState
   stateCurrent As CState

   Sub New
      Set stateUnassigned = New CStateUnassigned (Me)
      Set stateAssigned = New CStateAssigned (Me)
      Set stateReadyForTesting = New CStateSentToTesting (Me)
      Set stateCompleted = New CStateCompleted (Me)

      Set stateCurrent = stateUnassignedb
   End Sub

   Sub Assign()
      Call stateCurrent.TakeOver()
   End Sub

   Sub SendToTesting()
      Call stateCurrent.SendToTesting()
   End Sub

   Sub Complete()
      Call stateCurrent.Complete()
   End Sub

   Function GetAssignedState() As CState
      Set GetAssignedState = stateAssigned
   End Function

   Function GetReadyForTestingState() As CState
      Set GetReadyForTestingState = stateReadyForTesting
   End Function

   Function GetCompletedState() As CState
      Set GetCompletedState = stateCompleted
   End Function

   Sub SetState( state As CState )
      Set Me.stateCurrent = state
   End Sub
End Class</pre>
<p>And now, we need to implement all four states classes.</p>
<pre>Class CStateUnassigned As CState
   bugReport As CStateBugReport

   Sub New (bugReport As CStateBugReport)
      Set Me.bugReport = bugReport
   End Sub

   Sub TakeOver ()
      Messagebox "Took over!"
      Call Me.bugReport.SetState (Me.bugReport.GetAssignedState())
   End Sub

   Sub SendToTesting()
      Messagebox "Unassigned reports cannot be sent to testing"
   End Sub

   Sub Complete()
      Messagebox "Unassigned reports cannot be completed"
   End Sub
End Class

Class CStateAssigned As CState
   bugReport As CStateBugReport

   Sub New (bugReport As CStateBugReport)
      Set Me.bugReport = bugReport
   End Sub

   Sub TakeOver ()
      Messagebox "Report already assigned"
   End Sub

   Sub SendToTesting()
      Messagebox "Sent to testing!"
      Call Me.bugReport.SetState
         (Me.bugReport.GetReadyForTestingState())
   End Sub

   Sub Complete()
      Messagebox "Untested reports cannot be completed"
   End Sub
End Class

Class CStateSentToTesting As CState
   bugReport As CStateBugReport

   Sub New (bugReport As CStateBugReport)
      Set Me.bugReport = bugReport
   End Sub

   Sub TakeOver ()
      Messagebox "Report already assigned"
   End Sub

   Sub SendToTesting()
      Messagebox "Report already in testing"
   End Sub

   Sub Complete()
      Messagebox "Complete!"
      Call Me.bugReport.SetState (Me.bugReport.GetCompletedState())
   End Sub
End Class

Class CStateCompleted As CState
   bugReport As CStateBugReport

   Sub New (bugReport As CStateBugReport)
      Set Me.bugReport = bugReport
   End Sub

   Sub TakeOver ()
      Messagebox "Report already completed"
   End Sub

   Sub SendToTesting()
      Messagebox "Report already completed"
   End Sub

   Sub Complete()
      Messagebox "Report already completed"
   End Sub
End Class</pre>
<p>This is all there is to it. To test it, I wrote a simple agent that goes through states and in each new state also tests wrong transitions (e.g. from unassigned to complete etc.).</p>
<pre>Sub Initialize
	Dim bugReport As New CStateBugReport()

	Call bugReport.SendToTesting()
	Call bugReport.Complete()

	Call bugReport.Assign()
	Call bugReport.Assign()
	Call bugReport.Complete()

	Call bugReport.SendToTesting()
	Call bugReport.Assign()
	Call bugReport.SendToTesting()

	Call bugReport.Complete()
	Call bugReport.Assign()
	Call bugReport.SendToTesting()
	Call bugReport.Complete()
End Sub</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.lotushints.com/2009/03/design-patterns-part-8-state-pattern/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Design patterns &#8211; Part 7: Template method pattern</title>
		<link>http://www.lotushints.com/2009/02/design-patterns-part-7-template-method-pattern/</link>
		<comments>http://www.lotushints.com/2009/02/design-patterns-part-7-template-method-pattern/#comments</comments>
		<pubDate>Mon, 16 Feb 2009 08:00:35 +0000</pubDate>
		<dc:creator>Vladimir Kocjancic</dc:creator>
				<category><![CDATA[Best practices]]></category>
		<category><![CDATA[Code optimization]]></category>
		<category><![CDATA[design patterns]]></category>
		<category><![CDATA[Intermediate]]></category>
		<category><![CDATA[Lotus Domino]]></category>
		<category><![CDATA[Object-oriented development]]></category>
		<category><![CDATA[custom classes]]></category>
		<category><![CDATA[LotusScript]]></category>
		<category><![CDATA[maintenance]]></category>
		<category><![CDATA[object-oriented]]></category>
		<category><![CDATA[template method]]></category>

		<guid isPermaLink="false">http://www.lotushints.com/?p=200</guid>
		<description><![CDATA[In this article, I would like to present you a design pattern that is not so common, but for sure, I wish, that in the past I would have used it. It would certainly make my life much easier. So, what is this Template method pattern all about? The Template Method Pattern defines the skeleton [...]]]></description>
			<content:encoded><![CDATA[<p>In this article, I would like to present you a design pattern that is not so common, but for sure, I wish, that in the past I would have used it. It would certainly make my life much easier. So, what is this Template method pattern all about?</p>
<blockquote><p><strong>The Template Method Pattern</strong> defines the skeleton of a an algorithm in one method. Some steps are deferred to subclasses, which are allowed to alter certain algorithm steps without changing the skeleton of an algorithm.</p></blockquote>
<p><span id="more-200"></span></p>
<p><strong>Say what?</strong></p>
<p>Well, to simplify the definition, let&#8217;s look at an example. Imagine you have several product types. Your assigned task was to build a product catalogue on the web. All product types will use tables for representation, however not all products can be displayed the same. This is a perfect task for Template method pattern.</p>
<p><strong>But why?</strong></p>
<p>Think about it. Your catalogue needs to be displayed differently for each product, meaning you need to get different sets of product for each display. I agree, you could have written multiple agents, or just use multiple methods in an agent, but think about maintainability. And on top of it all, to display each product type, your algorithm is the same. First you need to do some <strong>initialization</strong>, then you need to <strong>select</strong> desired products. Next step is to <strong>process</strong> document set to create a display. In the end, all you need to do is <strong>print</strong> the results and <strong>terminate</strong> (or perform a clean up). Steps <strong>select</strong> and <strong>process</strong> are product type dependant. All other steps of the algorithm are common.</p>
<p><strong>Example</strong></p>
<p>For example let&#8217;s pretend that we have two types of products: regular classroom courses and e-courses. Regular classroom courses (or just courses) are scheduled courses, while e-courses are actually a 1 month subscription to some content (like video, PDF, etc.).</p>
<p>First, we need to create some storage classes: CProduct and CPrice, that will store information about products. This is more efficient than just have a collection of NotesDocuments.</p>
<pre>Class CPrice
	Public strDesc As String
	Public dPrice As Double
End Class

Class CProduct
	m_strName As String
	m_strType As String
	Public m_Price() As CPrice

	Property Get Label As String
		Label = Me.m_strName
	End Property

	Property Get MyType As String
		MyType = Me.m_strType
	End Property

	Sub New (strName As String, strType As String)
		Me.m_strName = strName
		Me.m_strType = strType
		Redim Me.m_Price (0)
	End Sub

	Sub AddPrice (strDesc As String, dPrice As Double)
		Dim nIndex As Integer

		nIndex = 0
		If (Not Me.m_Price (0) Is Nothing) Then
                     nIndex = Ubound (Me.m_Price) + 1
              End If

		Redim Preserve Me.m_price (nIndex)
		Set Me.m_price (nIndex) = New CPrice
		Me.m_Price (nIndex).strDesc = strDesc
		Me.m_Price (nIndex).dPrice = dPrice
	End Sub
End Class</pre>
<p>Class CPrice contains a description of price (subscription or schedule date) and the price itself. Class CProduct defines a product. Each product can have multiple prices.</p>
<p>Now, to our abstract class that will define the algorithm and required methods.</p>
<pre>Class CTemplateProduct
	m_strHtml As String
	m_products() As CProduct

	Sub Initialize()
		Redim m_products (0)
	End Sub

	Sub Select()
	End Sub

	Sub Process()
	End Sub

	Sub Print()
		Print m_strHtml
	End Sub

	Sub Terminate()
		Erase m_products
	End Sub

	Sub Run()
		Call Me.Initialize()
		Call Me.Select()
		Call Me.Process()
		Call Me.Print()
		Call Me.Terminate()
	End Sub
End Class</pre>
<p>As you can see, methods Initialize, Print and Terminate are already implemented.<br />
Next, we need to create classes for each product type. These classes will inherit from the abstract class.</p>
<pre>Class CTemplateCourse As CTemplateProduct
   Sub Select()
      Redim Preserve Me.m_products (1)
      Set Me.m_products (0) =
         New CProduct ("Course 1", "Lecture")

      Call Me.m_products (0).AddPrice ("Feb 3rd, 2009", 1000.0)

      Set Me.m_products (1) =
         New CProduct ("Exam 1", "Lecture &amp; exam")

      Call Me.m_products (1).AddPrice ("Feb 20th, 2009", 2000.0)
   End Sub

   Sub Process()
      Dim n As Integer
      Dim nPrice As Integer
      Dim nLBound As Integer
      Dim nUBound As Integer
      Me.m_strHtml = {&lt;table border="0"&gt;}

      For n = Lbound (Me.m_products) To Ubound (Me.m_products)
         Me.m_strHtml = Me.m_strHtml &amp; {&lt;tbody&gt;&lt;tr&gt;}
         Me.m_strHtml = Me.m_strHtml &amp; {&lt;td colspan="2"&gt;}
         Me.m_strHtml = Me.m_strHtml &amp; _
         Me.m_products (n).Label &amp; { - }

         Me.m_strHtml = Me.m_strHtml &amp; _
         Me.m_products (n).MyType &amp; {&lt;/td&gt;}

         Me.m_strHtml = Me.m_strHtml &amp; {&lt;/tr&gt;}
         Me.m_strHtml = Me.m_strHtml &amp; {&lt;tr&gt;}

         nLBound = Lbound(Me.m_products (n).m_Price)
         nUBound = Ubound (Me.m_products (n).m_Price)
         For nPrice = nLBound To nUBound
            Me.m_strHtml = Me.m_strHtml &amp; {&lt;td&gt;}
            Me.m_strHtml = Me.m_strHtml &amp; _
            Me.m_products (n).m_Price (nPrice).strDesc 

            Me.m_strHtml = Me.m_strHtml &amp; {&lt;/td&gt;}
            Me.m_strHtml = Me.m_strHtml &amp; {&lt;td&gt;}
            Me.m_strHtml = Me.m_strHtml &amp; _
            Me.m_products (n).m_Price (nPrice).dPrice
            Me.m_strHtml = Me.m_strHtml &amp; {&lt;/td&gt;}
         Next
         Me.m_strHtml = Me.m_strHtml &amp; {&lt;/tr&gt;}
      Next

      Me.m_strHtml = Me.m_strHtml &amp; {&lt;/tbody&gt;}
   End Sub
End Class

Class CTemplateECourse As CTemplateProduct
   Sub Select()
      Redim Preserve Me.m_products (1)
      Set Me.m_products (0) =
         New CProduct ("E-Course 1", "eBook")
      Call Me.m_products (0).AddPrice ("1 month", 100.0)

      Set Me.m_products (1) =
         New CProduct ("E-Course 2", "ePresentation")

      Call Me.m_products (1).AddPrice ("1 month", 200.0)
   End Sub

   Sub Process()
      Dim n As Integer
      Dim nPrice As Integer
      Dim nLBound As Integer
      Dim nUBound As Integer

      Me.m_strHtml = {&lt;table border="0"&gt;}

      For n = Lbound (Me.m_products) To Ubound (Me.m_products)
         Me.m_strHtml = Me.m_strHtml &amp; {&lt;tbody&gt;&lt;tr&gt;}
         Me.m_strHtml = Me.m_strHtml &amp; {&lt;td&gt;} &amp;_
         Me.m_products (n).Label &amp; {&lt;/td&gt;}
         Me.m_strHtml = Me.m_strHtml &amp; {&lt;td&gt;} &amp; _
         Me.m_products (n).MyType &amp; {&lt;/td&gt;}

         nLBound = Lbound(Me.m_products (n).m_Price)
         nUBound = Ubound (Me.m_products (n).m_Price)
         For nPrice = nLBound To nUBound
            Me.m_strHtml = Me.m_strHtml &amp; {&lt;td&gt;} &amp; _
            Me.m_products (n).m_Price (nPrice).strDesc

            Me.m_strHtml = Me.m_strHtml &amp; {&lt;br/&gt;} &amp; _
            Me.m_products (n).m_Price (nPrice).dPrice &amp; {&lt;/td&gt;}
         Next
         Me.m_strHtml = Me.m_strHtml &amp; {&lt;/tr&gt;}
      Next

      Me.m_strHtml = Me.m_strHtml &amp; {&lt;/tbody&gt;&lt;/table&gt;}
   End Sub
End Class</pre>
<p>As you can no doubt see, I have simplified the Select method (this is due to me being to lazy to actually create a form, a view and some 6 documents). Also, method Process creates different HTML for each product type.</p>
<p>Interesting thing, this is about it.<br />
All you have to do is some code that will use this. Here is my test agent, that should be run via browser.</p>
<pre>Sub Initialize
	Dim course As CTemplateProduct
	Dim eCourse As CTemplateProduct

	Set course = New CTemplateCourse ()
	Call course.Run()

	Set eCourse = New CTemplateECourse()
	Call eCourse.Run()
End Sub</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.lotushints.com/2009/02/design-patterns-part-7-template-method-pattern/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Design patterns &#8211; Part 6: Observer pattern</title>
		<link>http://www.lotushints.com/2009/02/design-patterns-part-6-observer-pattern/</link>
		<comments>http://www.lotushints.com/2009/02/design-patterns-part-6-observer-pattern/#comments</comments>
		<pubDate>Mon, 09 Feb 2009 08:00:33 +0000</pubDate>
		<dc:creator>Vladimir Kocjancic</dc:creator>
				<category><![CDATA[Basic]]></category>
		<category><![CDATA[Best practices]]></category>
		<category><![CDATA[Code optimization]]></category>
		<category><![CDATA[design patterns]]></category>
		<category><![CDATA[Intermediate]]></category>
		<category><![CDATA[Lotus Notes]]></category>
		<category><![CDATA[Object-oriented development]]></category>
		<category><![CDATA[custom classes]]></category>
		<category><![CDATA[LotusScript]]></category>
		<category><![CDATA[object-oriented]]></category>
		<category><![CDATA[observer]]></category>

		<guid isPermaLink="false">http://www.lotushints.com/?p=183</guid>
		<description><![CDATA[One of the most used patterns is also a pattern that hears by the name Observer. What does it do? Well, imagine you have a stock portfolio and you need to notify your investors every time the value of their stock changes. First, your investors need to subscribe to the stock they would like to [...]]]></description>
			<content:encoded><![CDATA[<p>One of the most used patterns is also a pattern that hears by the name Observer. What does it do? Well, imagine you have a stock portfolio and you need to notify your investors every time the value of their stock changes. First, your investors need to <strong>subscribe</strong> to the stock they would like to be notified about. Next, whenever new stock value is <strong>published</strong>, subscribers are notified. Much like RSS subscription. But what about definition:</p>
<blockquote><p><strong>The Observer pattern</strong> defines a one-to-many dependency between objects so that when one object changes state, all of its dependants are notified and updated automatically.</p></blockquote>
<p><span id="more-183"></span><br />
<strong>Fine, but what can I do with that?</strong></p>
<p>We will build an above mentioned example of a stock and it&#8217;s investors. First, you will need to create an observer abstract class:</p>
<pre>Class CObserver
	m_strName As String

	Property Get ObserverName As String
		ObserverName = Me.m_strName
	End Property

	Sub New (strName As String)
		Me.m_strName = strNAme
	End Sub

	Sub Update()
	End Sub
End Class</pre>
<p>As you can see, it contains a name, which will be used as unique id, a constructor, where the name is set and subroutine called Update that will be called when new value of our stock will be set.</p>
<p>Now, that we have an observer, we can create a subject class that will be an abstract class used by our stock.</p>
<pre>Class CObserverSubject
	m_oList List As CObserver

	Sub Attach (observer As CObserver)
	  If (Not Iselement (m_oList (observer.ObserverName))) Then
	     Set m_oList (observer.ObserverName) = observer
	  End If
	End Sub

	Sub Detach (observer As CObserver)
	  If (Iselement (m_oList (observer.ObserverName))) Then
	     Erase m_oList (observer.ObserverName)
	  End If
	End Sub

	Sub Notify ()
		Forall observer In m_oList
			Call observer.Update()
		End Forall
	End Sub
End Class</pre>
<p>The class contains list of all investors (observers) and operations to add (Attach ()) or remove (Detach ()) them. There is also routine Notify, that will update each and every investor.</p>
<p>Framework is now set. Moving on to concrete classes. First, we will create a concrete subject class called ObserverStock.</p>
<pre>Class CObserverStock As CObserverSubject
	m_strName As String
	m_dValue As Double

	Property Get StockName As String
		StockName = Me.m_strName
	End Property

	Property Get Value As Double
		Value = Me.m_dValue
	End Property

	Property Set Value As Double
		Me.m_dValue = Value
		Call Notify()
	End Property

	Sub New (strName As String, dValue As Double)
		Me.m_strName = strName
		Me.m_dValue = dValue
	End Sub
End Class</pre>
<p>The class inherits from ObserverSubject class. Also, it has a property for obtaining stock name and properties for obtaining and setting stock value. However, when setting stock value, not only value is set, but there is also a call to Notify method, specified in ObserverSubject class. This will notify all subscribers of new value.</p>
<p>The only thing missing now is observer concrete class called ObserverInvestors.</p>
<pre>Class CObserverInvestor As CObserver
	m_Stock As CObserverStock

	Property Get Stock As CObserverStock
		Set Stock = Me.m_Stock
	End Property

	Property Set Stock As CObserverStock
		Set Me.m_Stock = Stock
	End Property

	Sub New (strName As String)
	End Sub

	Sub Update()
		Messagebox Me.m_strName &amp; ": " &amp;_
		m_Stock.StockName &amp; " value is " &amp; m_Stock.Value
	End Sub
End Class</pre>
<p>And it is simple enough. It needs a constructor with name as parameter (due to his parent class), a property that ties stock to the class and Update () function that will ideally send an e-mail to investors, but in this case just pops up a message with investor and stock info.</p>
<p><strong>Usage of previous classes</strong></p>
<p>To use previously stated classes, I wrote an agent that will create a stock, add three investors to it, and change value. Then, last observer will be removed from notification list and value will be updated again. When running this agent, you should first get three pop up messages and then only two.</p>
<pre>Sub Initialize
	Dim observer As CObserverInvestor
	Dim stock As CObserverStock

	Set stock = New CObserverStock ("MyStock", 120.0)

	Set observer = New CObserverInvestor ("Investor 1")
	Set observer.Stock = stock
	Call stock.Attach (observer)

	Set observer = New CObserverInvestor ("Investor 2")
	Set observer.Stock = stock
	Call stock.Attach (observer)

	Set observer = New CObserverInvestor ("Investor 3")
	Set observer.Stock = stock
	Call stock.Attach (observer)

	stock.Value = 100.0

	Call stock.Detach (observer)
	stock.Value = 102.5
End Sub</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.lotushints.com/2009/02/design-patterns-part-6-observer-pattern/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Design patterns &#8211; Part 5: Adapter pattern</title>
		<link>http://www.lotushints.com/2009/01/design-patterns-part-5-adapter-pattern/</link>
		<comments>http://www.lotushints.com/2009/01/design-patterns-part-5-adapter-pattern/#comments</comments>
		<pubDate>Mon, 12 Jan 2009 08:00:29 +0000</pubDate>
		<dc:creator>Vladimir Kocjancic</dc:creator>
				<category><![CDATA[Basic]]></category>
		<category><![CDATA[Code optimization]]></category>
		<category><![CDATA[design patterns]]></category>
		<category><![CDATA[Lotus Notes]]></category>
		<category><![CDATA[adapter]]></category>
		<category><![CDATA[custom classes]]></category>
		<category><![CDATA[LotusScript]]></category>
		<category><![CDATA[object-oriented]]></category>
		<category><![CDATA[Object-oriented development]]></category>

		<guid isPermaLink="false">http://www.lotushints.com/?p=162</guid>
		<description><![CDATA[Another quite useful pattern is Adapter pattern. Adapters represent an interface between two different classes. For example imagine being a continental EU citizen travelling to UK. For you to plug in to UK power plug, you need an adapter that will take the interface your connector has and output the interface UK power plug demands. [...]]]></description>
			<content:encoded><![CDATA[<p>Another quite useful pattern is Adapter pattern. Adapters represent an interface between two different classes. For example imagine being a continental EU citizen travelling to UK. For you to plug in to UK power plug, you need an adapter that will take the interface your connector has and output the interface UK power plug demands.<span id="more-162"></span><br />
Definition of Adapter pattern is:</p>
<blockquote><p>The<strong> Adapter pattern</strong> converts the interface of a class into an interface the client expects. Adapter lets classes work together even if they couldn&#8217;t otherwise due to incompatible interfaces.</p></blockquote>
<p><strong>So how does this work in practice?</strong></p>
<p>You will mostly need adapters when you will obtain code from someone else. But just for the sake of simplicity, we will look into unlikely scenario, when you will get a code that prints &#8220;Hello World!&#8221; and write an adaptor that displays &#8220;Hello adapters!&#8221; in message box using the same interface.</p>
<p>First you need a client class and it&#8217;s interface. As we know, interfaces are not implemented in LotusScript. Thus, an abstract class will be used instead. Then we&#8217;ll need a client class. Both are pasted below:</p>
<pre>Class CHelloWorldInterface
	Sub printText ()
	End Sub
End Class

Class CHelloWorld As CHelloWorldInterface
	Sub printText ()
		Print "Hello World!"
	End Sub
End Class</pre>
<p>Now, we need to create our interface that displays &#8220;Hello adapters!&#8221; in message box.</p>
<pre>Class CHelloAdaptersInterface
	Sub msgboxText ()
	End Sub
End Class

Class CHelloAdapters As CHelloAdaptersInterface
	Sub msgboxText ()
		Messagebox "Hello Adapters!"
	End Sub
End Class</pre>
<p>All we need now is an adapter.</p>
<pre>Class CHelloAdpatersAdapter As CHelloWorldInterface
	m_helloAdapter As CHelloAdaptersInterface

	Sub new (helloAdapter As CHelloAdaptersInterface)
		Set Me.m_helloAdapter = helloAdapter
	End Sub

	Sub printText()
		Call m_helloAdapter.msgboxText()
	End Sub
End Class</pre>
<p>And to bind it together, here is an agent that will output both results.</p>
<pre>Sub Initialize
	Dim hw As CHelloWorld
	Dim ha As CHelloAdapters
	Dim haa As CHelloWorldInterface

	Set hw = New CHelloWorld ()
	Set ha = New CHelloAdapters ()
	Set haa = New CHelloAdaptersAdapter (ha)

	'test HelloAdapters
	Call ha.msgboxText()

	'test HelloWorld
	Call testHello (hw)

	'test HelloAdaptersAdapter
	Call testHello (haa)
End Sub

Sub testHello (hello As CHelloWorldInterface)
	Call hello.printText()
End Sub</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.lotushints.com/2009/01/design-patterns-part-5-adapter-pattern/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Design patterns &#8211; Part 4: Factory method pattern</title>
		<link>http://www.lotushints.com/2008/12/design-patterns-part-4-factory-method-pattern/</link>
		<comments>http://www.lotushints.com/2008/12/design-patterns-part-4-factory-method-pattern/#comments</comments>
		<pubDate>Mon, 15 Dec 2008 08:00:51 +0000</pubDate>
		<dc:creator>Vladimir Kocjancic</dc:creator>
				<category><![CDATA[Code optimization]]></category>
		<category><![CDATA[design patterns]]></category>
		<category><![CDATA[Intermediate]]></category>
		<category><![CDATA[Object-oriented development]]></category>
		<category><![CDATA[LotusScript]]></category>
		<category><![CDATA[singleton]]></category>

		<guid isPermaLink="false">http://www.lotushints.com/?p=148</guid>
		<description><![CDATA[Factory method pattern definition: The Factory method pattern defines an interface for creating and objects, but lets subclasses to decide which class they will create. Huh? I will try to present this pattern on a simple example. Imagine you work in a company that sales software. However, this software is, due to different laws, different [...]]]></description>
			<content:encoded><![CDATA[<p>Factory method pattern definition:</p>
<blockquote><p>The Factory method pattern defines an interface for creating and objects, but lets subclasses to decide which class they will create.</p></blockquote>
<p><strong>Huh?</strong></p>
<p>I will try to present this pattern on a simple example. Imagine you work in a company that sales software. However, this software is, due to different laws, different for each country/region it is sold in (in our case EU and USA). You have two types of software (Pro and Basic that differ by price and package). You will need to create a single store that will allow users to only buy products from their country.<span id="more-148"></span></p>
<p>First, you can create an abstract class that will represent a product.</p>
<pre>Class CSoftware
	m_strName As String

	Property Get ProductName As String
		ProductName = Me.m_strName
	End Property

	Sub New
	End Sub

	Sub PreparePackage ()
	End Sub

	Sub PrintPrice ()
	End Sub
End Class</pre>
<p>As you can see, the class itself is pretty simple. It contains a member variable for product name and has two methods that will prepare a package and print it&#8217;s price.<br />
Now (as you need two product types for two countries) you need to create 4 product classes that will inherit from CSoftware class. I will only show you both EU classes as others are pretty self explanatory.</p>
<pre>Class CEUSoftwareBasic As CSoftware
	Sub New
		Me.m_strName = "EU Basic"
	End Sub

	Sub PreparePackage ()
		'TODO: put your code here
	End Sub

	Sub PrintPrice ()
		'TODO: put your code here
	End Sub
End Class

Class CEUSoftwarePro As CSoftware
	Sub New
		Me.m_strName = "EU Pro"
	End Sub

	Sub PreparePackage ()
		'TODO: put your code here
	End Sub

	Sub PrintPrice ()
		'TODO: put your code here
	End Sub
End Class</pre>
<p>There. You are done with products. Now, you need two stores, that will create desired products. But first, you should create an abstract store class.</p>
<pre>Class CSoftwareStore
	Function orderSoftware (swtype As String) As CSoftware
		Dim sw As CSoftware

		Set sw = createSoftwarePackage (swtype)
		Call sw.PreparePackage ()
		Call sw.PrintPrice ()

		Set orderSoftware = sw
	End Function

	Function createSoftwarePackage (swtype As String) As CSoftware
	End Function
End Class</pre>
<p>As you can see, createSoftwarePackage method is empty. This is because createSoftwarePackage differs from store to store. Method orderSoftware, though, is the same for all stores and can be implemented in abstract class.<br />
Now, a source of both stores that inherit from CSoftwareStore.</p>
<pre>Class CEUSoftwareStore As CSoftwareStore
	Function createSoftwarePackage (swtype As String) As CSoftware
		Dim sw As CSoftware

		Select Case (Lcase (swtype))
		Case "basic": Set sw = New CEUSoftwareBasic ()
		Case "pro": Set sw = New CEUSoftwarePro ()
		End Select

		Set createSoftwarePackage = sw
	End Function
End Class

Class CUSASoftwareStore As CSoftwareStore
	Function createSoftwarePackage (swtype As String) As CSoftware
		Dim sw As CSoftware

		Select Case (Lcase (swtype))
		Case "basic": Set sw = New CUSASoftwareBasic ()
		Case "pro": Set sw = New CUSASoftwarePro ()
		End Select

		Set createSoftwarePackage = sw
	End Function
End Class</pre>
<p>Each store creates and returns an object depending on the type we wanted.</p>
<p><strong>But what will that bring me?</strong></p>
<p>You will only have to know which store you need to use and not care about the product returned. That is a job of each separate store. Thus, your code will be easier to read and to maintain.<br />
Pasted below is a sample execution code.</p>
<pre>Sub Initialize
	Dim storeEU As CEUSoftwareStore
	Dim storeUSA As CUSASoftwareStore
	Dim sw As CSoftware

	Set storeEU = New CEUSoftwareStore ()
	Set storeUSA = New CUSASoftwareStore ()

	Set sw = storeEU.orderSoftware ("basic")
	Print "Package: " &amp; sw.ProductName

	Set sw = storeUSA.orderSoftware ("pro")
	Print "Package: " &amp; sw.ProductName
End Sub</pre>
<p>The agent creates both stores and then for each store orders a software. Printed results should be:</p>
<pre>Package: EU Basic
Package: USA Pro</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.lotushints.com/2008/12/design-patterns-part-4-factory-method-pattern/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Design patterns &#8211; Part 3: Singleton pattern</title>
		<link>http://www.lotushints.com/2008/11/design-patterns-part-3-singleton-pattern/</link>
		<comments>http://www.lotushints.com/2008/11/design-patterns-part-3-singleton-pattern/#comments</comments>
		<pubDate>Mon, 24 Nov 2008 08:00:59 +0000</pubDate>
		<dc:creator>Vladimir Kocjancic</dc:creator>
				<category><![CDATA[Code optimization]]></category>
		<category><![CDATA[design patterns]]></category>
		<category><![CDATA[Intermediate]]></category>
		<category><![CDATA[Object-oriented development]]></category>
		<category><![CDATA[LotusScript]]></category>
		<category><![CDATA[singleton]]></category>

		<guid isPermaLink="false">http://www.lotushints.com/?p=128</guid>
		<description><![CDATA[The simplest way to describe singleton class is to look at the definition: The Singleton Pattern ensures a class has only one instance, and provides a point of access to it. So why would you need that? Well, there are many objects you only need one of in your application (e.g. Logging, text trimming, for [...]]]></description>
			<content:encoded><![CDATA[<p>The simplest way to describe singleton class is to look at the definition:</p>
<blockquote><p><strong>The Singleton Pattern</strong> ensures a class has only one instance, and provides a point of access to it.</p></blockquote>
<p>So why would you need that? Well, there are many objects you only need one of in your application (e.g. Logging, text trimming, for loading strings from a view, etc.). It assures you that you only have one instance of the class and that no one can create another instance on its own. Thus, you need a global access point to deliver the handle to the class.<span id="more-128"></span></p>
<p><strong>How do we do that? </strong></p>
<p>I will use my text-trimming class (called CLimitedString) for this presentation.  The class is pretty simple. It&#8217;s basic task is to trim text after n characters and append &#8220;&#8230;&#8221; afterwards. Default limit is set to 30, but user can set other value via Limit property.</p>
<pre>Private Class CLimitedString
    Private m_nLimit As Integer

    Public Sub New ()
        'setting default value
        Me.m_nLimit = 30
    End Sub

    Public Property Get Limit As Integer
        Limit = Me.m_nLimit
    End Property

    Public Property Set Limit As Integer
        Me.m_nLimit = Limit
    End Property

    Public Function Process (source As String) As String
        If (Len (source) &lt; Me.Limit) Then
            Process = source
            Exit Function
        End If

        Process = Strleftback (Left (source, Me.Limit), " ") &amp;_
        "..."
    End Function
End Class</pre>
<p>As LotusScript does not support private constructors, we will have to create a private class instead. This means that you won&#8217;t be able to access this class from anywhere else but this ScriptLibrary. Thus, we need to create a global variable to store class instance and a script library function as a global point of access.<br />
Variable:</p>
<pre>Private currLimitedString As CLimitedString</pre>
<p>Script library function:</p>
<pre>Function GetLimitedStringInstance As Variant
    If (currLimitedString Is Nothing) Then
        Set currLimitedString = New CLimitedString
    End If

    Set GetLimitedStringInstance = currLimitedString
End Function</pre>
<p>As your class is private, this function must return <strong>Variant</strong>, as code using this class isn&#8217;t aware of class&#8217; existence. The usage of the object remains the same.</p>
<p><strong>How do I call my class?</strong></p>
<p>It is quite simple. All you need to do is include your library into an agent for example and then do the following where needed:</p>
<pre>...
Dim vLimitedString As Variant
...
vLimitedString = GetLimitedStringInstance
vLimitedString.Limit = 10
Messagebox vLimitedString.Process ("My very first singleton class")</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.lotushints.com/2008/11/design-patterns-part-3-singleton-pattern/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Lotus Developer 2008 Europe Report</title>
		<link>http://www.lotushints.com/2008/11/lotus-developer-2008-europe-report/</link>
		<comments>http://www.lotushints.com/2008/11/lotus-developer-2008-europe-report/#comments</comments>
		<pubDate>Mon, 17 Nov 2008 08:00:04 +0000</pubDate>
		<dc:creator>Vladimir Kocjancic</dc:creator>
				<category><![CDATA[Code optimization]]></category>
		<category><![CDATA[design patterns]]></category>
		<category><![CDATA[Lotus Domino]]></category>
		<category><![CDATA[Lotus Notes]]></category>
		<category><![CDATA[Object-oriented development]]></category>
		<category><![CDATA[Sametime]]></category>
		<category><![CDATA[Upgrades]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[ACL]]></category>
		<category><![CDATA[LotusScript]]></category>

		<guid isPermaLink="false">http://www.lotushints.com/?p=121</guid>
		<description><![CDATA[Day 0, Check-in The flight was OK, check-in without issues and registration to the conference was prompt, which scared the hell out of me. You know what they say. If everything goes right, something is bound to go terribly wrong. Conference registration people were kind enough to give me shoulder bag with loads and loads [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Day 0, Check-in</strong></p>
<p>The flight was OK, check-in without issues and registration to the conference was prompt, which scared the hell out of me. You know what they say. If everything goes right, something is bound to go terribly wrong.<br />
Conference registration people were kind enough to give me shoulder bag with loads and loads of commercials, a ticket to Blackberry Bold draw and a conference guide, which was probably the most useful item. If you don&#8217;t count the bag that is.<br />
Then, off to the city I was for some gift shopping.<span id="more-121"></span></p>
<p><strong>Day 1, Nothing new to start with day</strong></p>
<p>So, keynote address was predictable. IBM owns Microsoft was the golden line. Apparently Notes are mostly stalled at the same level, with organic growth to make our world better.</p>
<p>Next, I went to the lecture about best practices of building decent UI&#8217;s. It was the same as last year, and the year before. The only really useful stuff was listener&#8217;s input about Layer Tree, which you can use to hide each separate layer and thus ease your UI development. It is located under <strong>Design-&gt;Layer Tree</strong>.</p>
<p>The lecture about new enhancements in Lotus Notes 8 was a great session. It&#8217;s main focus was on new functions in @Formula, LotusScript and Java. The most interesting new functions are inter-collection operations from DocumentCollection and ViewEntryCollection classes.</p>
<p>Next was a session on composite applications basics. The examples were based on Lotus Notes 8 mail and contacts template, which owned. There was bunch of undocumented features that can make almost any application look like Notes Mail/Contacts, with several drawbacks. Like the one that you cannot alter design of the database after you have made it look like Mail/Contacts. Well, not without changing the design of Mail/Contacts in the process.</p>
<p>Last session was delivered by Chris Miller about installing Sametime 8. Loads of useful stuff which I will try to cover in my future postings. Well at least basics of it. Btw, if you have ST GW and it doesn&#8217;t work, even though you can see it connected to Yahoo and Sametime community, it can be that your port number is false. When you get approved, you need to change to 5060 port instead of 5061 which is set by default. You should get notified about this, but it really depends on who did the actual provisioning.</p>
<p><strong>Day 2, Xpages And Composite applications everywhere</strong></p>
<p>First session of the day was about new Domino Designer 8.5. Focus was on Xpages, which don&#8217;t work well with Javascript disabled. Other than that, Agents editor is old style. Still. Probably will be better in 8.5.1, but it is not included in beta yet, so I doubt it will see the light prior 8.5.2. The funny thing is, Script libraries use Eclipse editor and it looked awesome.</p>
<p>Next it was Julian Robichaux explaining how to trap errors. Most of it was focused on his open source database called OpenLog, which is quite nice centralized database for storing error reports.</p>
<p>The birds of a feather session about Mobilizing Lotus applications was decent. If your company is supporting Blackberry or Windows Mobile.</p>
<p>Session about WebServices in Domino 7 was pretty exciting. Got some excellent gotcha&#8217;s and definitely some more enthusiasm of using web services in future applications. Bill Buchan was great and really made sure that even some dull facts became interesting.</p>
<p>Last session was basically a beginner&#8217;s tutorial on Composite applications. Perhaps I will try to sum it up in one of my next postings, as it really opens lots of application usability options. It was an excellent session and it made me even more sure that Composite applications are a great thing in Notes 8.</p>
<p><strong>Day 3, The conference concludes</strong></p>
<p>First session was delivered by Bill Buchan about Advanced OO programming in LotusScript. It was a great way to renew my knowledge of OO development. There was an example of Singleton pattern, which I will do in the future in this blog as well. Also, there was a note of double dot notation which enables you to call a parent class function from overridden function in your own class.</p>
<p>Second session was about management of ACL. It scared me. Specially, since I can distinctly remember that at a certain bank I was auditing their ACL had several Defaults set to Manager. Well most. Rob Axelrod gave a great lecture about reducing database ACL to acceptable level for all types of databases.</p>
<p>Next was Lance Spellman with creating client plugins for Lotus Notes. The session was more or less just a tutorial to build a window in Lotus Notes client. If you are interested in something more, turn to books on creating Eclipse plug-ins. Anyway, it was an essential demo, that showed, how much do you have to do, to actually create a plugin for Notes. Is it useful? Probably, if you have signing certificate. Otherwise your clients will get that nice do not install plug-in warning.</p>
<p>Last session I skipped, even though it sounded much more interesting. However, I had an air plane to catch. So that was it for me. Goodbye Lotus Developer 2008 and Amsterdam.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lotushints.com/2008/11/lotus-developer-2008-europe-report/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

