Presentation is loading. Please wait.

Presentation is loading. Please wait.

SYNERGY 2007 Design Patterns and the Object Factory Miami Thursday, May 17th Peter Bragg, Care Data Systems.

Similar presentations


Presentation on theme: "SYNERGY 2007 Design Patterns and the Object Factory Miami Thursday, May 17th Peter Bragg, Care Data Systems."— Presentation transcript:

1 SYNERGY 2007 Design Patterns and the Object Factory Miami Thursday, May 17th Peter Bragg, Care Data Systems

2 The Company (Background) Care Data Systems Limited Based in Birmingham, UK Dataflex users since 1985 Employed that handsome, young fellow Peter Bragg on September 18 th 2001 Senior Product Developer

3 The Product (Background) Donorflex Comprehensive system designed to support the ‘Not for Profit’ sector – donations management (financial control, gift aid, gifts in kind, merchandise sales) – fundraising and strategic development (campaign management & control) – relationship management (profiling, segmentation, targeting) – operational support (acknowledgements, communications, action plans) – events management (charity events and third party fundraising and sponsorship)

4 Typical Clients (Background) Healthcare Education Arts Community Social Services Overseas Aid Disability Services Political Reform Religious Organisations Service Veterans Sport

5

6 Design Patterns and the Object Factory

7 The Story Begins… January 17 th 2007

8 Design Patterns & the Object Factory

9 I answered the question so precisely that no further comments were required! (Erm…) No one is interested in Factories No one is using Factories Might make an interesting topic?

10 Design Patterns & the Object Factory I am not a Design Pattern Expert..at all! Knowledge limited to ‘what I do’

11 Design Patterns & the Object Factory Creational Design Patterns and the Object Factory …in donorflex

12 Design Patterns & the Object Factory Our Design Need:  One Application (donorflex)  Different backends (Dataflex, MSSQL, ?)  Intelligent code optimisation/execution

13 Design Patterns & the Object Factory Possible design solutions:  If, Else or Case Statements  Deferred creation of ‘Process’ Objects The need:  Call a process (e.g. a ‘search’) and execute code appropriate for the backend.

14 Design Patterns & the Object Factory View Object (i.e. Enquiry) Process Object (i.e. Enquiry Engine) Procedure OnProcess If (Backend=Dataflex) … end else if (Backend=MSSQL)… end etc. End_Procedure

15 Design Patterns & the Object Factory View Object (i.e. Enquiry) Procedure DoRunEnquiry Handle hoEnquiryEngine If (Backend=Dataflex) Get Create U_ … to hoEnquiryEngine else if (Backend=MSSQL) Get Create U_ ……. Send DoProcess of hoEnquiryEngine send Destroy of hoEnquiryEngine End_Procedure

16 Design Patterns & the Object Factory View Object (i.e. Enquiry) Factory Object (oFactory) Responsible for creating appropriate Process Object Procedure DoRunEnquiry Send DoProcess of (Instance(oFactory(self))) End_Procedure

17 So how does it all hang together? Write different versions of a (business) process as classes:  cAbstractPowerSearch (defines interface)  cPowerSearch_df is a cAbstractPowerSearch  cPowerSearch_mssql is a cAbstractPowerSearch Classes are then registered with a “Factory”:

18 Design Patterns & the Object Factory Class cPowerSearchEnq_Factory is a cFactory Procedure Construct_Object Forward Send Construct_Object Send RegisterType Factory_Type_Dataflex U_cPowerSearch_DF Send RegisterType Factory_Type_MSSQL U_cPowerSearch_MSSQL End_Procedure End_Class

19 So how does it all hang together? An instance of the factory is then added to a view Object oPowerSearchEnq Is A cPowerSearchEnq_Factory End_Object A call is then made to an ‘Instance’ of this Factory So instead of: Send DoProcess of oPowerSearchEnq We would code: Send DoProcess of (Instance(oPowerSearchEnq(self))) A ‘singleton’ Factory Controller instructs the Factory which version of the process to create

20 Factory Controller Class Enum_List Define Factory_Type_Dataflex Define Factory_Type_MSSQL Define Factory_Type_Pervasive Define Factory_Type_MySQL Define All_Factory_Types//need to be last – gives number of defined types End_Enum_List Class cFactoryController is a cObject Procedure Construct_Object String sEngine Forward Send Construct_Object Property Integer piCurrentType Factory_Type_Dataflex // Default type. // Check the application object: Get psFactoryEngine of ghoApplication to sEngine //set during OnCreate of Application object Case Begin Case (sEngine = "mssql") Set piCurrentType to Factory_Type_MSSQL Case Break Case End End_Procedure // Construct_Object Function CurrentType Returns Integer Function_Return (piCurrentType(Self)) End_Function End_Class

21 Factory Controller Object Global_Variable Handle ghFactoryController Get Create of Desktop U_cFactoryController to ghFactoryController

22 The Factory Class Class cFactory is a cObject Procedure Construct_Object integer[] iTypeMappings Forward Send Construct_Object // Holds the type of the current factory object: Property Integer piInstanceType (CurrentType(ghFactoryController)) // Holds the object instance that this factory object represents: Property Handle phInstance 0 // Initially zero. // Array that holds class identifiers to be constructed dependant on the required type: Property Integer[] piTypeMappings //initialise piTypeMappings Array to avoid index out of range errors move 0 to iTypeMappings[All_Factory_Types] Set piTypeMappings to iTypeMappings End_Procedure // Construct_Object // Provides a means by which to 'register' what class should be used against a particular type of connection: Procedure RegisterType Integer iType Integer iClass integer[] iTypeMappings Get piTypeMappings to iTypeMappings move iClass to iTypeMappings[iType] Set piTypeMappings to iTypeMappings End_Procedure

23 The Factory Class… // Returns the class associated by a previous call to RegisterType: Function TypeClass Integer iType Returns Integer Integer iClass integer[] iTypeMappings Get piTypeMappings to iTypeMappings move iTypeMappings[iType] to iClass // if we don't find a registered class of the type we are looking for, look for and return the native dataflex // factory type.. if (iClass = 0) move iTypeMappings[Factory_Type_Dataflex] to iClass // Support drop through the default // type. // if we still have no registered class, we must give an error if (iClass = 0) Error 4113 ("Programmatic Error - No registered type for factory "+name(self)) Function_Return iClass End_Function // Returns the current 'type' associated with this factory: Function InstanceType Returns Integer Function_Return (piInstanceType(Self)) End_Function // Allows a new type to be set against this object: Procedure Set InstanceType Integer iType Set piInstanceType to iType End_Procedure

24 The Factory Class… // Returns or creates the correct instance of a type for this factory: Function Instance Returns Handle Handle hObj Integer iType iNewType Get phInstance to hObj Get InstanceType to iType Get CurrentType of ghFactoryController to iNewType // If the type doesn't match what we are currently using then destroy the object and create a new one: If ((iType <> iNewType) And (hObj <> 0)) Begin Send Destroy of hObj Move 0 to hObj End If (Not(hObj)) Begin Get Create (TypeClass(Self, iNewType)) to hObj Set phInstance to hObj Set InstanceType to iNewType End Function_Return hObj End_Function // Boolean function that tells the caller if the factory instance has been created yet: Function IsCreated Returns Boolean Function_Return (phInstance(self) <> 0) End_Function End_Class

25 A Simple Example User logs in and we look to see if they have any communications to make. Code we execute will depend on the backend So we will use a factory for this…

26 A Simple Example Use cFactory.pkg Define the interface: class cAbstractLoginPrompts is a cObject Function DoFindLoginPrompts string sUser date dDate integer iDays returns integer[] end_function end_class Or sometimes.. class cAbstractLoginPrompts is a cObject Function DoFindLoginPrompts string sUser date dDate integer iDays returns integer[] Error DFErr_Program “Method not defined for concrete class” end_function end_class

27 A Simple Example Write the classes: class cLoginPrompts_df is a cAbstractLoginPrompts Function DoFindLoginPrompts string sUser date dDate integer iDays returns integer[] integer[3] iRetVal //outstanding/today/future integer iOverdue iToday iFuture open doncomms For_All DONCOMMS BY Index.3 Constrain Doncomms.On_behalf_of EQ sUser Constrain Doncomms.Login_prompt EQ "Y" DO if (doncomms.date < dDate) increment iOverdue else if (doncomms.date = dDate) increment iToday else if (doncomms.date <= (dDate+iDays-1)) increment iFuture End_For_All move iOverdue to iRetVal[0] move iToday to iRetVal[1] move iFuture to iRetVal[2] function_return iRetVal end_function end_class

28 A Simple Example class cLoginPrompts_sql is a cAbstractLoginPrompts Function DoFindLoginPrompts string sUser date dDate integer iDays returns integer[] integer[3] iRetVal //outstanding/today/future integer iFetchResult iCount iData handle hSQLInstance hConn hSQL string sSQL sDate sDateFuture sBase boolean bNoMoreResultSets move (Instance(ghSQLConnectionFactory)) to hSQLInstance move ("Select count(*) from doncomms where doncomms.On_behalf_of = '"+sUser+"' and doncomms.Entity = 'R' and doncomms.Login_prompt = 'Y' and ") to sBase Get DateToSQL of hSQLInstance dDate to sDate move (sSQL+sBase+"doncomms.Date < '"+sDate+"';") to sSQL move (sSQL+sBase+"doncomms.Date = '"+sDate+"';") to sSQL Get DateToSQL of hSQLInstance (dDate+1) to sDate Get DateToSQL of hSQLInstance (dDate+iDays-1) to sDateFuture move (sSQL+sBase+"doncomms.date between '"+sDate+"' and '"+sDateFuture+"';") to sSQL // Open Connection Get Connection of hSQLInstance to hConn Get SQLOpen of hConn to hSQL // Send the Statement.. Send SQLExecDirect of hSQL sSQL move False to bNoMoreResultSets

29 A Simple Example Repeat Get SQLFetch Of hSQL To iFetchResult If (iFetchResult <> 0) begin move (trim(SQLColumnValue(hSQL,1))) to iData increment iCount move iData to iRetVal[iCount-1] end Get SQLNextResultSet of hSQL to iFetchResult if (not(iFetchResult)) move True to bNoMoreResultSets Until (bNoMoreResultSets) // Release the Statement: Send SQLClose of hSQL function_return iRetVal end_function end_class

30 A Simple Example Write a factory class and register both classes: class cLoginPrompts_Factory is a cFactory Procedure Construct_Object Forward Send Construct_Object // Register the default class that will be used as a drop through if other types aren't // registered: Send RegisterType Factory_Type_DataflexU_cLoginPrompts_df Send RegisterType Factory_Type_MSSQLU_cLoginPrompts_sql End_Procedure end_Class Create an Object instance of the Factory Object oLoginPromptsFactory is a cLoginPrompts_Factory End_object

31 A Simple Example Then call the function and let the factory do the rest Integer[] iRetVal Get DoFindLoginPrompts of (instance(oLoginPromptsFactory(Self))) sUser dDate iDays to iRetVal Under the hood: The function “Instance” asks “have I already created an object for you?” If so, it simply returns a handle to the object it created earlier If not:  It looks to see what the “Factory Controller” says it should be creating  It creates an object of the required class  It sets a property with the handle of the object  It returns a handle to the object  “DoFindLoginPrompts” is then executed

32 Another Example:

33 How it works… Use dnTreeView.pkg Use cProfileFactory.pkg class cProfileTree is a dnTreeView Import_Class_Protocol Server_Mixin Procedure Construct_Object forward send Construct_Object Property Integer piPrivate.CurrentProfile 0 Property Integer piPrivate.HelpArray_ID 0 Property Handle phProfileTreeFactory (Create(self,U_cProfileTree_Factory)) Send Define_Server // Set tree properties: Set TreeLinesState to False Set TreeRootLinesState to False Object PopupMenu is a cProfilePopUpMenu Delegate Set PopupMenu_ID to Self End_Object end_procedure

34 How it works…

35 Design Patterns & the Object Factory Using this ‘Factory’ approach as a model:  “The need to know” - objects only get involved with what they need to. Views simply make a call to a common interface and don’t care about what lies behind this.  Scalability – new classes can be written and registered with a Factory very easily.  Easy to code and implement new factory instances.

36 SYNERGY 2007 Thank You Miami Thursday, May 17th


Download ppt "SYNERGY 2007 Design Patterns and the Object Factory Miami Thursday, May 17th Peter Bragg, Care Data Systems."

Similar presentations


Ads by Google