How to implement singleton design pattern in C++?

Example (template parameter allows to encapsulate any data)

#include <iostream>

// C++ 03
template <class T>
class S_03
{
public:
static S_03<T>& getInstance()
{
    // Guaranteed to be destroyed. 
    // Instantiated on first use.
    static S_03<T> instance;   
    return instance;
}

T& getData()
{
    return data;
}

private:
    // Any data contained by singleton.
    T data;                    

S_03<T>() {}

// C++ 03
// ========
// Don't forget to declare these two. You want to make sure they
// are unacceptable otherwise you may accidentally get copies of
// your singleton appearing.

// Copying constructor. Don't Implement!
S_03<T>(S_03<T> const&);        
// Assignment operator. Don't implement!
void operator=(S_03<T> const&); 
};

// C++ 11
template <class T>
class S_11
{
public:
static S_11<T>& getInstance()
{
    // Guaranteed to be destroyed. 
    // Instantiated on first use.
    static S_11<T> instance;    
    return instance;
}

T& getData()
{
    return data;
}

private:
    // Any data contained by singleton.
    T data;                     

S_11<T>() {}

public:
// C++ 11
// =======
// We can use the better technique of deleting the methods
// we don't want.
S_11<T>(S_11<T> const&) = delete;
void operator=(S_11<T> const&) = delete;
};

class Data 
{
public:
    int value;

    Data() {}
};

typedef S_03<Data> S_03_Data;
typedef S_11<Data> S_11_Data;

int main()
{
    S_03_Data::getInstance().getData().value = 10;
    S_11_Data::getInstance().getData().value = 20;

    using namespace std;
    cout << S_03_Data::getInstance().getData().value << endl;
    cout << endl;

    cout << S_11_Data::getInstance().getData().value << endl;
    cout << endl;

    return 0;
}

Read more

Advertisements

How to design plug-in modules in Pascal

The example shows dependency inversion pattern in which 3 application layers are separated by abstraction layers represented by sets of interfaces.

Sample hierarchy of application layers
Sample hierarchy of application layers.

Application uses a few classes (curve types) which are designed to be static plug-ins. Static means that application should be rebuilt after adding/removing plug-ins. Every class is defined in separate module and is inherited from base type. Every class should register itself in the application by calling RegisterCurveType method of the container class. This is performed in implementation part of module. Container class is a singleton and responsible for keeping and providing information about available curve types to the application. Container is responsible also for creating instances of curve classes. To register itself class should create instance of the singleton and call registration method. To add/exclude curve type to/from the application it is enough to add/exclude curve module to/from the project.

An example of class hierarchy
An example of class hierarchy.

IPointsSet

type
    { Interface defining basic operation for creating curve type. }
    IPointsSet = interface
        { Sets unique identifier of curve type. }
        procedure SetCurveTypeId(CurveTypeId: TCurveTypeId);
        { Sets name of curve type. The method is used in deserializing
          objects received from server. }
        procedure SetCurveTypeName(Name: string);
        { Returns unique identifier of curve type. }
        function GetCurveTypeId: TCurveTypeId;
        { Returns name of curve type. It's better to use function
          instead of property because property assumes storing data
          in object, but storing any data is not necessary in this case. }
        function GetCurveTypeName: string;
    end;

TCurveTypesSingleton

type
    { Class-singleton containing information about curve types. }
    TCurveTypesSingleton = class(TCBRCComponent,
        ICurveFactory, ICurveTypeIterator, ICurveTypeSelector)
    private
        FCurveTypes: TList;
        { Current curve type used in iteration. }
        FCurrentCurveType: TCurveType;
        { Curve type selected by user. }
        FSelectedCurveType: TCurveType;

        class var FCurveTypesSingleton: TCurveTypesSingleton;
        constructor Init;

    public
        class function Create: TCurveTypesSingleton;
        procedure RegisterCurveType(CurveClass: TCurveClass);
        { Implementation of ICurveFactory. }
        function CreatePointsSet(TypeId: TCurveTypeId): TNamedPointsSet;
        { Implementation of ICurveTypeIterator. }
        procedure FirstCurveType;
        procedure NextCurveType;
        function EndCurveType: Boolean;
        function GetCurveTypeName: string;
        function GetCurveTypeId: TCurveTypeId;
        function GetCurveTypeTag(CurveTypeId: TCurveTypeId): Integer;
        { Implementation of ICurveTypeSelector. }
        procedure SelectCurveType(TypeId: TCurveTypeId);
        { Returns value of FCurrentCurveType. The value should be checked on Nil. }
        function GetSelectedCurveType: TCurveTypeId;
    end;  

ICurveFactory

type
    { Interface defining basic operation for creating curve instances. }
    ICurveFactory = interface
        function CreatePointsSet(TypeId: TCurveTypeId): TNamedPointsSet;
    end;

ICurveTypeIterator

type
    { Interface defining basic operation for iterating through curve types. }
    ICurveTypeIterator = interface
        procedure FirstCurveType;
        procedure NextCurveType;
        function EndCurveType: Boolean;
        function GetCurveTypeName: string;
        function GetCurveTypeId: TCurveTypeId;
    end;

ICurveTypeSelector

type
    { Interface defining basic operation for selecting curve type. }
    ICurveTypeSelector = interface
        procedure SelectCurveType(TypeId: TCurveTypeId);
        function GetSelectedCurveType: TCurveTypeId;
    end;

 

Curve type registration

var CTS: TCurveTypesSingleton;

initialization
    CTS := TCurveTypesSingleton.Create;
    CTS.RegisterCurveType(TUserPointsSet);
end.    

Example was taken from the project fit

Continue reading

An example of singleton pattern in Pascal

type
    TCurveTypesSingleton = class
    private
        class FCurveTypesSingleton: TCurveTypesSingleton;
        constructor Init;
    public
        class function Create: TCurveTypesSingleton;
    end;

implementation

constructor TCurveTypesSingleton.Init;
begin
    inherited Create;
end;

class function TCurveTypesSingleton.Create: TCurveTypesSingleton;
begin
    if FCurveTypesSingleton = nil then
      FCurveTypesSingleton := TCurveTypesSingleton.Init;
    Result := FCurveTypesSingleton;
end;

Example was taken from the project fit

Continue reading

An example of dependency injection pattern

In the example two kinds of classes are defined: “data loaders” and “injectors”. “Data loaders” are responsible for reading data from specific file format, “injectors” are responsible for providing client with implementation of “data loader” according to some criteria. Both kinds implement specific interfaces from abstraction layer. This allows to add new “data loaders” and “injectors” without modification of client. Injector should be responsible for keeping and freeing instance of data loader.

An illustration of dependency inversion principle and dependency injection pattern
An illustration of dependency inversion principle and dependency injection pattern.

Example was taken from the project fit