What options are there in the Spring4D framework that we don’t know about, but are very usable? Well, actually quite a lot. One of them is the Factory Pattern. It comes in very handy when you want to apply the open/closed principle. Your code is open for extension, but closed for modification.
A classic example is working with enumerations or numbers that indicate a certain state. This quickly creates all kinds of conditional structures that have to be adapted as soon as a new status or value is added. In the example below, certain code is executed depending on an invoice status. To split the code, the factory pattern was applied.
This is the definition of invoice and status:
TInvoiceStatus = (New, Sent, Overdue, Paid);
TInvoice = class
function Status: TInvoiceStatus;
To use the factory pattern, we include the Spring.DesignPatterns unit.
Next, we define the factory. It consists of a key value and a function that returns the method you want to execute. That sounds complex, but it’s not so bad. In our case, the key value is the invoice status (TInvoiceStatus). The function we want to execute has invoice (TInvoice) as a parameter. The definition for the factory then looks like this:
TProcessInvoiceProc = reference to procedure(const Invoice: TInvoice);
TInvoiceProcessor = class
FFactory: TFactory<TInvoiceStatus, TProcessInvoiceProc >;
procedure TInvoiceProcessor .InitialiseFactory;
FFactory := TFactory<TInvoiceStatus, TProcessInvoiceProc >.Create;
The code above already shows how the factory is created and initialised. Associated with each status is a “Process” function. This function returns the definition of the TProcessInvoiceProc to execute the code for that status. You define that as follows:
function TInvoiceProcessor .ProcessInvoiceNew: TProcessInvoiceProc;
Result := procedure(const Invoice: TInvoice)
ShowMessage('This is a new invoice');
Applying the factory is then easy and goes as visible in the code below:
procedure TInvoiceProcessor .ProcessInvoice(const Invoice: TInvoice);
if FFactory.IsRegistered(Invoice.Status) then
var Process := FFactory.GetInstance(Invoice.Status;)
This way, using the factory pattern, your code is easy to split and improve.