Skip to main content
A factory constructor in Dart is a constructor declared with the factory keyword that overrides the default instantiation behavior. Unlike generative constructors, which automatically allocate memory and initialize a new instance of the class, a factory constructor acts as a static method that must explicitly return an instance of the class or one of its subtypes.

Syntax and Mechanics

Factory constructors can be unnamed (the default constructor) or named. They are invoked using standard instantiation syntax, but internally, they execute a code block that dictates exactly what object reference is returned to the caller.
class User {
  final String name;

  // Private generative constructor
  User._internal(this.name);

  // Unnamed factory constructor
  factory User(String name) {
    return User._internal(name);
  }

  // Named factory constructor
  factory User.fromJson(Map<String, dynamic> json) {
    return User._internal(json['name']);
  }
}

Core Technical Constraints

  1. Explicit Return Requirement: A factory constructor must contain a return statement that yields an object of the declared type or a valid subtype. It does not implicitly return a newly allocated object.
  2. Absence of this Context: Because a factory constructor does not inherently allocate a new instance, it operates in a static context. It cannot access the this keyword, instance variables, or instance methods.

Returning Cached Instances

Because factory constructors do not strictly allocate new memory on every invocation, they can return previously instantiated objects. This mechanism is frequently used to manage shared state, return existing instances from a cache, or implement the Singleton pattern.
class DatabaseConnection {
  static final DatabaseConnection _instance = DatabaseConnection._internal();

  // Private generative constructor
  DatabaseConnection._internal();

  // Factory constructor returning a cached instance
  factory DatabaseConnection() {
    return _instance;
  }
}

Polymorphic Instantiation

Factory constructors are permitted to return instances of subclasses. This allows an abstract class or base class to dictate which concrete implementation is instantiated based on constructor arguments.
abstract class Shape {
  // Factory returning a subtype based on an argument
  factory Shape(String type) {
    if (type == 'circle') return Circle();
    if (type == 'square') return Square();
    throw ArgumentError('Unrecognized shape');
  }
}

class Circle implements Shape {}
class Square implements Shape {}

Redirecting Factory Constructors

Dart supports a specialized syntax for factory constructors that immediately delegate instantiation to another constructor, often in a subclass. This is known as a redirecting factory constructor. It uses the = operator and strictly omits the constructor body.
abstract class Logger {
  // Redirecting factory constructor
  factory Logger(String name) = ConsoleLogger;
}

class ConsoleLogger implements Logger {
  final String name;
  ConsoleLogger(this.name);
}

Factory vs. Static Methods

Mechanically, a factory constructor operates similarly to a static method that returns an instance of the class. The critical distinction is syntactic transparency at the call site. A factory constructor is invoked exactly like a generative constructor (e.g., final obj = MyClass();). This allows a developer to change a generative constructor to a factory constructor later in the development lifecycle without breaking existing implementation code that relies on standard instantiation syntax.
Tired of Poor Dart Skills? Fix That With Deep Grasping!Learn More