A factory constructor does not always build a fresh instance. It can pick an instance based on input, return a cached value, or fall back to a default. A library-private Color._(...) generative constructor builds the values the factory hands out.

Program

Play the program to ask for two colors and watch the factory dispatch to a known case and a fallback.

factory_constructors.dart
Replay: real traced execution (multi-file project)
class Color {
  final String name;
  final int code;
  Color._(this.name, this.code);

  factory Color.named(String name) {
    switch (name) {
      case 'red':
        return Color._('red', 1);
      case 'green':
        return Color._('green', 2);
      default:
        return Color._('unknown', 0);
    }
  }
}

void main() {
  var a = Color.named('red');
  var b = Color.named('purple');
  print('${a.name}=${a.code} ${b.name}=${b.code}');
}
  1. call ← Color.named('red')

    18void main() {19  var a = Color.named('red');20  var b = Color.named('purple');
    values this stepColor.named('red')call
  2. matched ← case 'red'

    6factory Color.named(String name) {7  switch (name) {8    case 'red':
    values this stepcase 'red'matchedredname
  3. return value ← Color(name: red, code: 1)

    8case 'red':9  return Color._('red', 1);10case 'green':
    values this stepColor(name: red, code: 1)return value
  4. a ← Color(name: red, code: 1)

    18void main() {19  var a = Color.named('red');20  var b = Color.named('purple');
    values this stepColor(name: red, code: 1)a
  5. call ← Color.named('purple')

    19var a = Color.named('red');20var b = Color.named('purple');21print('${a.name}=${a.code} ${b.name}=${b.code}');
    values this stepColor.named('purple')call
  6. matched ← default

    6factory Color.named(String name) {7  switch (name) {8    case 'red':
    values this stepdefaultmatchedpurplename
  7. return value ← Color(name: unknown, code: 0)

    12  default:13    return Color._('unknown', 0);14}
    values this stepColor(name: unknown, code: 0)return value
  8. b ← Color(name: unknown, code: 0)

    19var a = Color.named('red');20var b = Color.named('purple');21print('${a.name}=${a.code} ${b.name}=${b.code}');
    values this stepColor(name: unknown, code: 0)b
  9. print('${a.name}=${a.code} ${b.name}=${b.code}');

    20  var b = Color.named('purple');21  print('${a.name}=${a.code} ${b.name}=${b.code}');22}
    outputred=1 unknown=0
    values this stepColor(red, 1)aColor(unknown, 0)b
factory `factory Color.named(...)` returns an instance it chooses, instead of always creating a fresh one.
private constructor `Color._(...)` is a library-private generative constructor the factory uses to build values.
dispatch and fallback The factory inspects its argument and picks a case, with a `default` branch for unknown inputs.