Showing posts with label Creational Patterns. Show all posts
Showing posts with label Creational Patterns. Show all posts

Multiton Design Pattern in Delphi

The multiton is somewhat an extension of the singleton pattern. It is referred as registry of singletons by the GOF. I don’t know for sure who appointed the name multiton: it’s an analogy derived from the term singleton. So, singleton = single + ton; while multiton = multi + ton.

The singleton pattern guarantees that a class has only one instance; while the multiton allows keeping multiple instances by maintaining a map of related keys and unique objects.  Note that there can be only one instance per key when implementing the multiton pattern. Also, note that the key does not have to be a string value; it can be an object for example. Nonetheless, in our code sniped we will consider the key to be a string.

I am going to tweak my singleton class implementation so that I can make it a multiton instead:

unit Multiton;

interface

uses
  Generics.Collections;

type
  TMultiton = class
  private
    //Private fields and methods here...

     class var _registry: TDictionary<string, TMultiton>;
  protected

  public
    class function Create(aName: string): TMultiton;
    class destructor Destroy;
    class function Lookup(aName: string): TMultiton;
  
    destructor Destroy; override;

    //Other public methods and properties here...  
  end;

implementation

{ TMultiton }

class function TMultiton.Create(aName: string): TMultiton;
begin
  if not Assigned(_registry) then
    _registry:= TDictionary<string, TMultiton>.Create;

  if not _registry.TryGetValue(aName, Result) then
  begin
    Result:= inherited Create as Self;
    _registry.Add(aName, Result);
  end;
end;

class destructor TMultiton.Destroy;
begin
   if Assigned(_registry) then
   begin
     _registry.Values.ToArray[0].Free;     
   end;
end;

class function TMultiton.Lookup(aName: string): TMultiton;
begin
  if Assigned(_registry) then
    _registry.TryGetValue(aName, Result);
end;

destructor TMultiton.Destroy;
var
  _instance: TMultiton;
  ValuesArray: TArray<TMultiton>;         
begin
  if Assigned(_registry) then
  begin
    ValuesArray:= _registry.Values.ToArray;

    _registry.Clear;
    _registry.Free;
    _registry:= nil;

    for _instance in  ValuesArray do
      if _instance <> Self then
        _instance.Free;
  end;

  inherited;
end;

end.

A few things I want you to note:
  • Instead of a single instance, we are holding a registry of instances. We do so by introducing the class variable _registry of type TDictionary<string, TMultiton>.  
  • We register (create) the different instances by calling the class function Create. This function gets the key name as a parameter. A new instance is only created if no matches to the key name are found in the dictionary. If a match is found, then the corresponding value is returned from the dictionary data structure.
  • The Lookup class function allows retrieving a particular instance by giving its key name. Note that the Create function can also be used for this purpose, but it feels more natural to call Lookup for the searches, and Create for the registration (creation) of instances.
  • We have provided a regular destructor that once invoked releases all the memory: not only the current multiton instance, but the whole registry.    
  • We have also provided a class destructor in case that we forget to manually release the memory.  
This code was compiled with Delphi XE2, but it should also work for all versions above Delphi 2009. Comments, corrections and suggestions are most welcome.

Consider reading these books about design patterns if you haven’t yet:

Parameterized Factory Method in Delphi

Factory Method is a creational design pattern, whose intent (according to Design Patterns: Elements of Reusable Object-Oriented Software) is to:

“Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.”

Do you want to know more about design patterns? Check reference [1] at the bottom for extra reading.

In this post we will consider a variation of the pattern referred as parameterized factory method. This variation just refers to the first part of the intent, that is, “define an interface for creating an object”. Why is that?  What about the rest of the intent? Well, there are times in which sub-classing is not possible or not suitable; nonetheless, it is useful to define a factory method to encapsulate the creation of an object.

Let’s proceed with the example we used in our previous post (template design pattern); that is: Design an application that allows drawing different styles of houses (ei. country house, city house) using ASCII art.

The GUI of our app contains some VCL components as you can see in the images below. Clicking the buttons will result in an ASCII house printed out in the memo area. Depending on the Draw… button being clicked, the house will look differently: it can be a country house or a city house.
Factory Pattern Example (Delphi) – Country House

Figure1 A Country House (Draw Country House button was clicked)

Factory Pattern Example (Delphi) – City House

Figure 2 A City House (Draw City House button was clicked)


Behind the scenes, assume that we have implemented the following class hierarchy:

Factory Pattern Example (Delphi) – Class diagram

THouse is an abstract class that defines several methods for displaying the different parts of the house [2] or the house as a whole [3].

TCountryHouse and TCityHouse are two concrete (non-abstract) classes that actually override some of the methods of its superclass, allowing this way different look-and-feel; that is, a house in the country and a house in the city look differently.

When a button is clicked, the corresponding OnClick event is triggered. We have to provide logic (source code) to define what the button is going to do in response to the OnClick event. Using fancy words, we have to implement the event handler for the OnClick event. I have created the following event handler which is going to be shared by both buttons [4]:

//OnClick event handler for the buttons
procedure TfrmMain.btnDrawGenericHouseClick(Sender: TObject);
var
  House: THouse;
begin
  //If the "Sender" object is not a button do nothing
  if not(Sender is TButton) then Exit;

  //The concrete house object being created depends
  //on the button being clicked
  if TButton(Sender).Name = 'btnDrawCountryHouse' then
    House:= TCountryHouse.Create
  else if TButton(Sender).Name = 'btnDrawCityHouse' then
    House:= TCityHouse.Create;

  with House do
  begin
    //cmbHasChimney is a combo box (TComboBox) that allows
    //to decide whether to add a chimney or not to the house
    case cmbHasChimney.ItemIndex of
      0: HasChimney:= True;
      1: HasChimney:= False;
    end;
    //"memFrame" is a memo (TMemo) used to print out the house.
    memFrame.Text:= BuildIt;
    Free;
  end;
end;


This works of course, but it lacks flexibility. What happens if we want to add a third button, or a fourth, or a five in order to add new types of houses? In that case, you will have to rework the code above and the fragment in blue will grow up big as new house types are added. You will end coding something like this:

  if TButton(Sender).Name = 'btnDrawCountryHouse' then
    House:= TCountryHouse.Create
  else if TButton(Sender).Name = 'btnDrawCityHouse' then
   
House:= TCityHouse.Create
else if TButton(Sender).Name = 'btnDrawDogHouse' then
   
House:= TDogHouse.Create
else if TButton(Sender).Name = 'btnDrawTreeHouse' then
   
House:= TTreeHouse.Create
else if TButton(Sender).Name = 'btnDrawGhostHouse' then
   
House:= TGhostHouse.Create;

That is the only part changing within the method. Why don’t we take that chunk of code and place it somewhere else? For that, we can create a factory method. The factory method will take one parameter to decide the concrete house type to instantiate [4]. The return type of the factory method will be THouse, because THouse enfolds all the other house subtypes. What about this?

function TfrmMain.MakeHouse(Sender: TObject): THouse;
begin
  if TButton(Sender).Name = 'btnDrawCountryHouse' then
    Result:= TCountryHouse.Create
  else if TButton(Sender).Name = 'btnDrawCityHouse' then
   
Result:= TCityHouse.Create
else if TButton(Sender).Name = 'btnDrawDogHouse' then
   
Result:= TDogHouse.Create
else if TButton(Sender).Name = 'btnDrawTreeHouse' then
   
Result:= TTreeHouse.Create
else if TButton(Sender).Name = 'btnDrawGhostHouse' then
   
Result:= TGhostHouse.Create;
end;

MakeHouse is a parameterized factory method. It is called factory because its only purpose in life is to create an object. It is adorned with the parameterized term, because it takes a parameter (Sender) to decide the concrete class to instantiate.

What does this mean to our previous code (event handler method)? Well, see it by yourself:

//OnClick event handler for the buttons
procedure TfrmMain.btnDrawGenericHouseClick(Sender: TObject);
var
  House: THouse;
begin
  //If the "Sender" object is not a button do nothing
  if not(Sender is TButton) then Exit;

  //The concrete house object being created depends
  //on the button being clicked
  House:= MakeHouse(Sender); //See our factory method in action

  with House do
  begin
    //cmbHasChimney is a combo box (TComboBox) that allows
    //to decide whether to add a chimney or not to the house
    case cmbHasChimney.ItemIndex of
      0: HasChimney:= True;
      1: HasChimney:= False;
    end;
    //"memFrame" is a memo (TMemo) used to print out the house.
    memFrame.Text:= BuildIt;
    Free;
  end;
end;

Now, as you can see, the event handler will remain the same no matter how many different subtypes of houses we have (add). Everything about the creation of a house object is isolated in the factory method.

One final comment: Delphi is a hybrid programming language, allowing both structured and object oriented programming. In Delphi, we can have functions outside all classes’ scope. That’s not very Object Oriented. Isn’t? Besides, you can’t do that in languages like Java, Python, Ruby or C#.

In general, you should have a Factory class containing the factory method. In this particular Delphi example you might argue that we are just adding code for nothing. Yes, I give you that. But there are cases, in which having a hierarchy of factory classes comes naturally and the subfactories decide the concrete object to be created. We’ll cover that scenario in future posts :-)
 
Notes:

[1] Books about Design Patterns:



[2] BuildFloor(), BuildWalls(), BuildRoof(), BuildChimney(). These methods draw out the floor, walls, roof and chimney (if any) respectively.

[3] BuildIt(): this method calls the methods in [2] and as a result it draws the whole house.

[4] You can define the event handler for the buttons at design time using Delphi’s Object Inspector

Implementing the Singleton Design Pattern in Delphi without Global Variables

The purpose of this post is NOT to cover the insights and applicability of the Singleton pattern, instead  I just pretend to give you a Delphi code snipped that implements it. This implementation is focused in avoiding variables that are global to the unit (or Unit Global Variables).

Fist of all, I am borrowing the definition and UML diagram of the Singleton Design Pattern, as written in the Design Patterns: Elements of Reusable Object-Oriented Software book. I strongly suggest you to read this book if you want to have a deeper understanding of the classic design patterns.

Singleton: “Ensure a class only has one instance, and provide a global point of access to it.”

UML diagram:

UML diagram of the Singleton Design Pattern
For all Delphi versions previous to Delphi 7, the only way to implement this pattern is by using a Unit Global Variable, instead of a class static field. Fortunately, Delphi 7 featured class variables long time ago and this way, we can implement the pattern avoiding global scoped variables. For some reason, I have never seen an implementation of the Singleton pattern in Delphi using class variables, so here is my own:

unit Singleton;

interface

type
  TSingleton = class
  private
    //Private fields and methods here...
   
    (****************************************************)
    (*** Class variables were introduced in Delphi 7. ***)
    (*** Older Delphi versions should implement       ***)
    (*** this field as a unit global variable         ***)
     class var _instance: TSingleton;   
    (****************************************************)
  protected
    (*** Constructor is protected!!! ***)
    constructor Create;

    //Other protected methods here...
  public
    destructor Destroy; override;

    (********************************************)
    (*** Client code should use this function ***)

    (*** ("Instance"), instead of the         ***)
    (***
"constructor" to create (or access)  ***)
    (*** a singleton instance.                ***)
    class function Instance: TSingleton;
    (********************************************)
    

    class function NewInstance: TObject; override;

    //Other public methods and properties here...
  end;

implementation

{ TSingleton }

constructor TSingleton.Create;
begin
  inherited Create;
end;

destructor TSingleton.Destroy;
begin
  _instance:= nil;
  inherited;
end;

class function TSingleton.Instance: TSingleton;
begin
  if (_instance = nil) then
    _instance:= TSingleton.Create;

  result:= _instance;
end;



class function TSingleton.NewInstance: TObject;
begin
  if (_instance = nil) then
    _instance:= inherited NewInstance as Self;

  result:= _instance;

end;

end.


There was a problem with my original implementation. In Delphi:
  • Constructors are inherited (this doesn't happen in C++, Java, C#, etc.)
  • All classes inherit from TObject ultimately.
As TObject has its own constructor, the consumers of the TSingleton class can call it directly, allowing this way the creation of more than one instance. Ali, writer of the first comment in this article, pointed me in the right direction.  Thanks Ali.

I traduced Ali’s words into the source code above. The strikethrough text can be removed and the text in blue was added. This implementation ensures the singleness of the Singleton Design Pattern in Delphi.

Rethinking over this once again:

The implementation above ensures the class only has one instance; but it does not provide a global point of access to it. Instead of that, we now have two points of access. Take a look at the following code snipped:

  //Point of access ONE
  SingletonObject1:= TSingleton.Create;
 
  //Point of access TWO
  SingletonObject2:= TSingleton.Instance; 

Yes, two point of access: TSingleton.Create and TSingleton.Instance.

Rethinking this many times, I figured out the simplest implementation. We don’t even need to deal with the evil NewInstance class function. It looks like this:

unit Singleton;

interface

type
  TSingleton = class
  private
    //Private fields and methods here...

     class var _instance: TSingleton;
  protected
    //Other protected methods here...
  public
    //Global point of access to the unique instance
    class function Create: TSingleton;

    destructor Destroy; override;

    //Other public methods and properties here...
  end;

implementation

{ TSingleton }

class function TSingleton.Create: TSingleton;
begin
  if (_instance = nil) then
    _instance:= inherited Create as Self;

  result:= _instance;
end;

destructor TSingleton.Destroy;
begin
  _instance:= nil;
  inherited;
end;

end.

The only point of access to the singleton instance is the class function “Create”, which hides the TObject.Create parameterless constructor (more details here). Now we have only one instance and a global point of access to it.

The comments inside the above code are self-explanatory. Furthermore, for those stuck with older Delphi versions, the Singleton pattern should be implemented as follows:

unit Singleton;

interface

type
  TSingleton = class
  private
    //Private fields and methods here...
  protected
    //Other protected methods here...
  public
    //Global point of access to the unique instance
    class function Create: TSingleton;

    destructor Destroy; override;

    //Other public methods and properties here...
  end;


var
  _instance: TSingleton;
//Unit Global Variable.
 

implementation
...................

As a conclusion, I would suggest avoiding unit global variables as much as possible; in fact, as a rule of thumb, I would suggest to make your variables' scope as local as possible. This applies not only to this example (implementation of the Singleton Design Pattern), but to programming in general. Furthermore, the class variables in Delphi are equivalent to static member variables in C++, Java, C#...Class variables were introduced  in Delphi 7; so, previous versions should use global variables to implement a Singleton class.

Note:
There are three books about Design Patterns I would suggest you to read: