4D Blog

Home Product Singletons in 4D

Singletons in 4D

May 2, 2024

Product

4D 20 R5 delivers a powerful feature for developers: Singletons!

The singleton design pattern creates a single instance of a class accessible throughout your application.

This pattern offers many benefits, including:

  • host for interprocess values,
  • utility classes,
  • a base for the factory design pattern,
  • and many more.

Keep reading for more information about this new concept!

4D has 2 types of singletons: singletons, which are unique per process and shared singletons, which are unique across the application. Singletons are standard objects, while shared singletons are shared objects.

Defining a singleton is extremely easy; you just need to add the singleton keyword to a class constructor:

singleton Class constructor()

Defining a shared singleton is also very easy; you need to use the singleton keyword on a shared class:

shared singleton Class constructor()

From that moment on, you can easily access your singletons through the me attribute:

$singleton:=cs.SingletonClass.me

The me attribute is the singleton instance (often accessed through the getInstance() function in other languages). It is instantiated the first time you access your singleton.

Examples

Singletons are very useful, and we expect you to start using them a lot. I think you’d prefer examples of singletons rather than a long description, so I’ve prepared a few.

Utility class

Let’s start with a simple example: the utility class. The utility class hosts many utility functions that are used everywhere in your application. Grouping these functions into a single class helps maintain your code, as it’s very easy to find all your utility functions, and they don’t clutter your methods.

//Class UtilityClass
 
singleton Class constructor()
 
Function utilityFunction1()
 
Function utilityFunction2()
 
...

From that moment on, you can call your utility functions with this line:

cs.UtilityClass.me.utilityFunction1()

Websocket server wrapper

Another classic use of singletons is to create wrappers for objects that should be accessible everywhere in your application, such as a websocket server. Let’s consider this class:

//WebSocketServerWrapper
 
singleton Class constructor()
 
$handler:=cs.myWebsocketServerHandler.new()
This.webSocketServer:=4D.WebSocketServer.new($handler; {dataType: “object”})
 
Function terminate()
 
This.webSocketServer.terminate()

From that moment on, you can start your Webserver by calling:

CALL WORKER(“WebSocketServerWorker”; Formula(cs.WebSocketServerWrapper.me))

And terminate it by calling:

CALL WORKER(“WebSocketServerWorker”; Formula(cs.WebSocketServerWrapper.me.terminate()))

Factory

The third example implements a design pattern: the factory. The factory is in charge of creating new instances of objects, in that case, Vehicle objects coming from a VehicleFactory:

//Class VehicleFactory
 
property vehicleBuilt:=0 //Number of vehicles built by the factory
 
shared singleton Class constructor()
 
shared Function buildVehicle($type : Text)->$vehicle : cs.Vehicle
 
  Case of
    : $type="car"
      $vehicle:=cs.Car.new()
    : $type="truck"
      $vehicle:=cs.Truck.new()
    : $type="sport car"
      $vehicle:=cs.SportCar.new()
    : $type="motorbike"
      $vehicle:=cs.Motorbike.new()
  Else
    $vehicle:=cs.Car.new()
  End case
 
  This.vehicleBuilt+=1

Thanks to being a Singleton, you can call this VehicleFactory to get a new Vehicle from everywhere in your application with a single line:

$vehicle:=cs.VehicleFactory.me.buildVehicle("truck")

In that case, this factory doesn’t do much besides counting the number of vehicles built before returning your new vehicle, but I think you get the idea.

The function buildVehicle modifies the VehicleFactory (by incrementing This.vehicleBuilt), so you also need to add the shared keyword to it so use and end use will be called automatically when calling and exiting the function.

Interprocess values

Another classic use of singletons is to host interprocess values that you’ll use all across your application. Here’s an example of such a singleton:

//Class InterprocessSingleton
 
shared singleton Class constructor()
 
This.version:=2
This.buildNumber:=1056

From there, you can access your global variables very easily, for example:

cs.InterprocessSingleton.me.version

Tip: Sometimes, you want to initialize your interprocess values at your application startup, typically inside the On Application Startup method, and in such case, you may need to pass parameters to the singleton constructor like in the example below:

//Class InterprocessSingleton
 
shared singleton Class constructor($file : 4D.File)
 
$json:=$file.getText()
$settingsJson:=JSON Parse($json)
 
This.version:=$settingsJson.version
This.buildNumber:=$settingsJson.buildNumber

In that case, the values of version and buildNumber come from a JSON file. In the case of singletons, there’s a way to call the constructor with parameters by calling the new() function. For example, in our case:

$myFile:=File("/RESOURCES/settings.json")
cs.InterprocessSingleton.new($myFile)

You must be careful that the call to new() is the first time the singleton has been accessed. Calling new() after the singleton has been accessed won’t call the class constructor anymore.

Special thanks

I want to give a special thank you to Chris Belanger, who suggested adding the me attribute to access a singleton.

I hope singletons are as exciting for you as they are for us. If you have any questions about them, feel free to ask them on the 4D forum.

Discuss

Tags 20 R5, 21, Class, Programming, Singleton

Latest related posts

  • June 16, 2025

    Generate, share and use web sessions One-Time Passcodes (OTP)

  • May 20, 2025

    Automatic Refresh of OEM Build Licenses

  • May 16, 2025

    New class to handle incoming TCP connections

Nicolas Brachfogel
Nicolas Brachfogel
Product Owner & Senior Developer - Nicolas Brachfogel joined 4D in 2017 as senior developer (4D Server and networking) and as Product Owner to manage the 4D version on Apple Silicon. He is tasked with the redaction of user stories and functional specifications, as well as the verification that the new features are in line with customers' needs. With a degree from Institut Supérieur d'Informatique Appliquée Paris (INSIA), Nicolas started his career as a software developer in 2001. After many years of development in Java and C++, he specialized himself in client-server development in the video game industry. As a developer/software architect, he worked on the server architectures of many games (Dofus Arena, Drakerz, Trivial Pursuit Go !).
  • Deutsch
  • Français
  • English
  • Português
  • Čeština
  • Español
  • Italiano
  • 日本語

Categories

Browse categories

  • 4D View Pro
  • 4D Write Pro
  • 4D for Mobile
  • Email
  • Development Mode
  • 4D Language
  • ORDA
  • User Interface / GUI
  • Qodly Studio
  • Server
  • Maintenance
  • Deployment
  • 4D Tutorials
  • Generic
  • 4D Summit sessions and other online videos

Tags

4D-Analyzer 4D for Android 4D for iOS 4D NetKit 4D Qodly Pro 4D View Pro 4D Write Pro 20 R8 20 R9 Administration Authentication Build application CI/CD Class Client/Server Code editor Collections Compatibility settings Formula Listbox Logs Mail Microsoft 365 Network Objects ORDA PDF Pictures Preemptive Programming Qodly Studio REST Scalability Security Session Source control Speed Spreadsheet Tutorial UI User Experience v20 vscode Web Word processor

Tags

4D-Analyzer 4D for Android 4D for iOS 4D NetKit 4D Qodly Pro 4D View Pro 4D Write Pro 20 R8 20 R9 Administration Authentication Build application CI/CD Class Client/Server Code editor Collections Compatibility settings Formula Listbox Logs Mail Microsoft 365 Network Objects ORDA PDF Pictures Preemptive Programming Qodly Studio REST Scalability Security Session Source control Speed Spreadsheet Tutorial UI User Experience v20 vscode Web Word processor
Subscribe to 4D Newsletter

© 2025 4D SAS - All rights reserved
Terms & Conditions | Legal Notices | Data Policy | Cookie Policy | Contact us | Write for us


Subscribe to 4D Newsletter

* Your privacy is very important to us. Please click here to view our Policy

Contact us

Got a question, suggestion or just want to get in touch with the 4D bloggers? Drop us a line!

* Your privacy is very important to us. Please click here to view our Policy