Dart Factory Constructors

Summary: in this tutorial, you’ll learn about dart factory constructors and how to apply them in practical examples.

Introduction to Dart factory constructors

A generative constructor always returns a new instance of the class. Therefore, it doesn’t use the return keyword.

Unlike a generative constructor, a factory constructor uses the factory keyword and uses a return keyword to return an instance of the class.

The factory constructor may return an existing instance rather than a new instance. For example, it may return an instance from the cache. In addition, the factory constructor may return an instance of a subtype of the class.

Factory constructor example

The following example illustrates how to use a factory constructor:

class Logger {
  final String name;
  bool muted = false;
  static final _cache = <String, Logger>{};

  Logger._create(this.name);

  factory Logger(String name) =>
      _cache.putIfAbsent(name, () => Logger._create(name));

  void log(String message) {
    if (!muted) {
      print(message);
    }
  }
}

void main() {
  var logger = Logger('console');
  logger.log('Hello');

  // load the same logger from the cache
  var logger2 = Logger('console');
  logger2.log('Bye');
}Code language: Dart (dart)

How it works.

First, define the Logger class that has two properties name and _cache.

The name property holds the name of a logger’s instance:

final String name;Code language: Dart (dart)

The _cache stores the mapping between the logger name and logger’s instances:

static final _cache = <String, Logger>{};Code language: Dart (dart)

The type of the _cache is Map that manages a collection of key/value pairs. Note that you’ll learn more about the Map type later.

Second, define a private named constructor _create that initializes the name instance variable:

Logger._create(this.name);Code language: Dart (dart)

Third, define a factory constructor that accepts a name. It returns an instance of the Logger if the name is not in the _cache. Otherwise, it creates a Logger object and adds the object to the cache:

factory Logger(String name) =>
      _cache.putIfAbsent(name, () => Logger._create(name));Code language: Dart (dart)

Fourth, define the log() function that displays a message to the console:

 void log(String message) {
    print(message);
  }Code language: Dart (dart)

Finally, create two loggers with the same name and log messages to the console. Since we use the same logger name, the factory constructor returns the same Logger object from the cache:

void main() {
  var logger = Logger('console');
  logger.log('Hello');

  // load the same logger from the cache
  var logger2 = Logger('console');
  logger2.log('Bye');

  print(identical(logger, logger2)); // true
}Code language: Dart (dart)

The identical() function proves that logger and logger2 reference the same object.

Summary

  • Use the factory keyword to define a factory constructor that returns an instance of the class (or its subclass).
Was this tutorial helpful ?