Sitemap

The Factory Constructor in Dart and Flutter

3 min readApr 11, 2025

--

Press enter or click to view image in full size

In object-oriented programming (OOP), a constructor is a method that creates and initializes objects of a class. It has the same name as the class and is responsible for reserving the necessary memory for each object. In addition, it can be used to initialize the class’s attributes, either through parameters or internally, hiding the logic. To do this, in Dart, you need to create a named constructor.

class Point {
// Instance variables to hold the coordinates of the point.
double x;
double y;

// Generative constructor with initializing formal parameters:
Point(this.x, this.y);

// Named constructor, no parameters, internally initialized:
Point.Origin() : x = 0, y = 0;
}

Obviously, it is possible to have named parameters instead of named constructors, allowing you to add a default value, and also avoiding positional parameters, making the code more readable.

class Point {
// Instance variables to hold the coordinates of the point.
double x;
double y;

// Generative constructor with named parameters:
Point({this.x = 0, this.y = 0});

}

// example
void main() {
Point point = Point(x: 0, y: 0);
}

One way to create constructor variations in Dart is by using the reserved word factory , which allows you to create a special constructor that returns an instance of an object. Very useful if you want to hide the creation logic or need to return an instance of subclasses based on parameters, similar to the design pattern Factory Method.

class Point {
// Instance variables to hold the coordinates of the point.
final double x;
final double y;

factory Point() {
return Point._internal(0,0);
}

factory Point.symmetric(double point) {
return Point._internal(point,-point);
}

Point._internal(this.x, this.y);
}

Note that _internal() was used, a private constructor that is normally used in conjunction with the factory. With it we can prevent the direct creation of instances. By using it we also guarantee flexibility, as we can change the internal implementation without affecting clients. Commonly used to implement the design pattern Singleton.

class DatabaseConnection {
static DatabaseConnection? _instance;
final String _connectionString;

factory DatabaseConnection(String connectionString){
_instance ??= DatabaseConnection._internal(connectionString);
return _instance!;
}

DatabaseConnection._internal(this._connectionString);
}

Factory Constructor in Flutter

In addition to being used in classes that represent models, we can use the factory in classes that represent visual components in Flutter, making the management of object creation more flexible, controllable, and standardized. For this, I use as an example a button that follows the same pattern, changing only its characteristics, such as the background color, border, and action when clicking.

Press enter or click to view image in full size
Buttons from design system of Null Academy

Such features can be encapsulated, avoiding repetition of the same code, and can be defined internally by a class that represents a variation of a generalization (subclass). To do this, we can create the AppButton that represents the base class and cannot be instantiated.

class AppButton extends StatelessWidget
{
final String label;
final Function() onTap;
final Color color;
final Color borderColor;

const AppButton._internal({
super.key,
required this.label,
required this.onTap,
required this.color,
required this.borderColor
});

///more code

With this we can start creating the AppButton variations. In the case above we have three types of buttons which I will name AppButton.primary(), AppButton.secondary() and AppButton.tertiary(), just to make it easier. For each of them we will pre-configure their specific colors.

  factory AppButton.primary({
Key? key,
required String label,
required Function() onTap,
}) {
return AppButton._internal(
key: key,
label: label,
onTap: onTap,
color: Color.fromARGB(255, 88, 204, 2),
borderColor: Color.fromARGB(255, 41, 90, 13)
);
}

See which part of the attributes were passed internally, leaving only the attributes that vary more frequently, and in addition we avoid repeating the same code, centralizing everything in the same point.

Did you get a better understanding of how to use Dart’s Factory constructor? Do you have any questions or find any errors? Let me know, comment below. See you later!👋

Press enter or click to view image in full size
Photo by Mohammad Rahmani on Unsplash

--

--

No responses yet