forbestheatreartsoxford.com

Understanding Factory Constructors in Dart/Flutter: An Overview

Written on

Introduction

Factory constructors may not be essential for developing a Flutter application, but they offer valuable functionality for various scenarios. These constructors can facilitate the singleton design pattern, aid in deserialization, help instantiate subclasses, or simply enhance code clarity. While factory constructors and static methods often appear similar, understanding their distinctions is key. This topic is aimed at those familiar with Dart and Flutter who wish to deepen their comprehension.

When to Use Factory Constructors?

Here, we will explore several scenarios where factory constructors are particularly beneficial, accompanied by code examples.

Singleton Pattern

Implementing the singleton pattern ensures that a class has only one instance. This is useful for complex classes that require significant computation or need to restrict access, such as a database connection. Below is an example demonstrating this concept, which can be tested on DartPad.

In this example, the database instance is created once (1). The constructor is private (2), ensuring that instantiation can only occur through the factory method, which always returns the same instance (3).

class Database {

static final Database _database = Database._internal(); // (1)

factory Database() => _database; // (3)

Database._internal(); // (2)

}

// Create the singleton

void main() {

Database db = Database();

Database db2 = Database();

print(identical(db, db2)); // true

}

Deserialization

Most applications interact with APIs, and when data is received as a map, you often want to create corresponding classes for easier manipulation. Factory constructors allow you to accept a map as input and produce an object. Check out this example of user deserialization on DartPad.

Here, user data is extracted from a map (1), which is a common practice. When the factory is invoked (2), it assigns specific keys to attributes of a user object (3).

class User {

final String name;

final int age;

User({required this.name, required this.age});

factory User.fromJson(Map<String, dynamic> json) => User(

name: json['name'],

age: json['age'],

); // (3)

}

// Use deserialization

void main() {

final karlMap = {

'name': 'Karl',

'age': 32,

}; // (1)

final karl = User.fromJson(karlMap); // (2)

print(karl.name); // Karl

print(karl.age); // 32

}

Instantiating Subclasses

Factory constructors enable the instantiation of different subclasses from a parent class, which can be advantageous when creating instances based on random factors or time.

Imagine a game where players first encounter easier enemies that become tougher over time. A ghost (1) represents a low-level foe, while a dragon (2) signifies a more formidable opponent. As players progress, they encounter more dragons (3,4). Although a static method could achieve this, using a factory constructor can yield a more elegant solution.

class Enemy {

final int strength = 0;

final String name = '';

factory Enemy.getEnemy({required int timeInSeconds}) {

if (timeInSeconds < 1000) {

return Ghost();

} else {

return Dragon();

}

}

}

class Ghost implements Enemy { // (1)

@override

final int strength = 10;

@override

final String name = "Ghost";

}

class Dragon implements Enemy { // (2)

@override

final int strength = 100;

@override

final String name = "Dragon";

}

void main() {

Enemy enemy = Enemy.getEnemy(timeInSeconds: 1); // (3)

print(enemy.strength); // prints 10

print(enemy.name); // prints Ghost

Enemy enemy2 = Enemy.getEnemy(timeInSeconds: 1000); // (4)

print(enemy2.strength); // prints 100

print(enemy2.name); // prints Dragon

}

Syntax Sugar

In some cases, opting for a factory constructor over a static method is preferable due to simpler syntax. These distinctions will be further discussed in the section on the difference between factory constructors and static methods.

What is the Difference Between a Factory Constructor and a Static Method?

While factory constructors can often be substituted with static methods, their unique features make them indispensable in certain scenarios. Renowned Flutter developer Remi Rousselet, known for creating popular packages like provider, riverpod, and freezed, provides insights into this distinction in his article. Here are some of his key points:

  • Factory constructors may be unnamed.
  • They do not require specifying generic parameters.
  • Naming a factory constructor eliminates the default constructor.
  • Factory constructors allow shorthand syntax for redirecting to other constructors.
  • They can be declared as const.
  • Factory constructors cannot be async.

For more details and examples, refer to Rousselet's original blog post.

Conclusion

While factory constructors can often be replaced with static methods, they offer specific advantages in terms of code readability and ease of use, particularly for singletons and subclass instantiation. If you have questions or additional insights, feel free to share your thoughts in the comments. I welcome any suggestions for future article topics as well.

If you enjoyed this article, please engage by clapping, highlighting, commenting, and sharing. Technical articles, in particular, have been affected by the recent changes to Medium's Partner Program, so your interaction is greatly appreciated!

Resources

  • Factory constructors (documentation, Dart)
  • Factory Constructors in Dart (YouTube, Programming Point)
  • Understanding Factory constructor code example — Dart (StackOverFlow, Ananta K Roy)
  • FACTORY CONSTRUCTOR IN DART (blog, dart-tutorial.com)
  • THE DIFFERENCE BETWEEN A “FACTORY CONSTRUCTOR” AND A “STATIC METHOD” (blog, dashoverflow [Remi Rousselet])
  • How do you build a Singleton in Dart? (StackOverFlow, Seth Ladd)

Share the page:

Twitter Facebook Reddit LinkIn

-----------------------

Recent Post:

Discover Essential Life Lessons Before It's Too Late

Explore vital lessons to learn early in life to avoid regrets and make the most of your journey.

Innovative Tools for Entrepreneurs Under $1,000

Discover six unique items under $1,000 that can enhance productivity for entrepreneurs, whether working remotely or in an office.

The Dynamic History of Earth's Tectonic Plates Unveiled

Discover the fascinating evolution of Earth's tectonic plates and their impact on our planet's landscape over billions of years.

Staying Alluring in Long-Term Relationships: More Than Just Looks

Exploring the essence of staying attractive in relationships beyond physical appearance.

Fossilized Tardigrades: Unveiling Ancient Secrets in Amber

Discover the remarkable find of a fossilized tardigrade in amber, shedding light on its history and biology.

Navigating Loneliness: Understanding the Psychology Behind It

Explore the complexities of loneliness and the essential human need for connection.

Navigating the Challenges of Humanizing AI-Generated Content

Explore the complexities of humanizing AI content and the importance of quality over quantity in marketing strategies.

# Embracing Self-Love Amidst Marital Struggles

In times of crisis, self-care is crucial. Embrace your worth and remember, brighter days lie ahead.