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

Details

Singleton ensures a class only has one instance, and provide a global point of access to it.

How It Works

  1. Create only one instance of the Singleton class; and

  2. If an instance exists, then serve the same object again.

The main features of Singleton are:

  • Ensuring that one and only one object of the class gets created;

  • Providing an access point for an object that is global to the program; and

  • Controlling concurrent access to resources that are shared.

When to Use It

  • In situations that require exactly one instance of a class, that must be accessible to clients from a well-known access point. See the Counter example.

Caution: Singletons can be a problem in multi-threaded applications, especially when they manipulate mutable data.

Tip: Singletons work well for immutable data, such as reading from some data source, since anything that can’t change isn’t going to run into thread clash problems.

See also

Other base design patterns: NullObject(), ValueObject()

Methods

Public methods


Method new()

Create or retrieve an object

Usage

Singleton$new()

Examples

# See more examples at <https://tidylab.github.io/R6P/articles> address <- function(x) sub('<environment: (.*)>', '\\1', capture.output(x)) # In this example we implement a `Counter` that inherits the qualities of # Singleton Counter <- R6::R6Class("Counter", inherit = R6P::Singleton, public = list( count = 0, add_1 = function(){self$count = self$count + 1; invisible(self)} )) # Whenever we call the constructor on `Counter`, we always get the exact same # instance: counter_A <- Counter$new() counter_B <- Counter$new() identical(counter_A, counter_B, ignore.environment = FALSE)
#> [1] TRUE
# The two objects are equal and located at the same address; thus, they are # the same object. # When we make a change in any of the class instances, the rest of the # instances are changed as well. # How many times has the counter been increased? counter_A$count
#> [1] 0
# Increase the counter by 1 counter_A$add_1() # How many times have the counters been increased? counter_A$count
#> [1] 1
counter_B$count
#> [1] 1