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).