What is the Factory Method Pattern?
The Factory Method Pattern is a creational design pattern that provides an interface for creating objects in a superclass, but allows subclasses to alter the type of objects that will be created.
In simple terms:
Instead of using new directly, you use a method (factory) to create objects.
When to Use Factory Method?
- When you want to control the instantiation of classes.
- When your code needs to work with objects without knowing their concrete types.
- When you need flexibility in object creation (especially with class hierarchies or dependencies).
Implementing Factory Method in Dart
Approach 1: Using Factory Constructor
dartCopyEditabstract class Button {
void render();
}
class AndroidButton implements Button {
@override
void render() {
print("Rendering Android-style Button");
}
}
class IOSButton implements Button {
@override
void render() {
print("Rendering iOS-style Button");
}
}
class ButtonFactory {
static Button createButton(String platform) {
if (platform == "android") {
return AndroidButton();
} else if (platform == "ios") {
return IOSButton();
} else {
throw Exception("Unsupported platform");
}
}
}
Example Usage:
dartCopyEditvoid main() {
var button1 = ButtonFactory.createButton("android");
var button2 = ButtonFactory.createButton("ios");
button1.render(); // Output: Rendering Android-style Button
button2.render(); // Output: Rendering iOS-style Button
}
Explanation:
Buttonis an abstract class (or interface).AndroidButtonandIOSButtonare concrete implementations.ButtonFactory.createButton()is the Factory Method that decides which object to create.
Approach 2: Factory Constructor in a Class
Dart also supports factory constructors built right into the class:
dartCopyEditclass Shape {
factory Shape(String type) {
if (type == "circle") return Circle();
if (type == "square") return Square();
throw Exception("Unknown shape type");
}
void draw() {}
}
class Circle extends Shape {
@override
void draw() {
print("Drawing a Circle");
}
}
class Square extends Shape {
@override
void draw() {
print("Drawing a Square");
}
}
void main() {
var shape1 = Shape("circle");
var shape2 = Shape("square");
shape1.draw(); // Drawing a Circle
shape2.draw(); // Drawing a Square
}
Benefits of Factory Method
- Centralizes object creation logic.
- Makes it easier to manage complex object hierarchies.
- Improves code flexibility and maintainability.
- Helps with Dependency Injection and testing.
Drawbacks
- Adds some complexity.
- Too many factories can lead to scattered object-creation logic.
- If overused, can be an anti-pattern (“Factory Hell”).
Tips & Best Practices
- Use factory methods for polymorphic object creation.
- Combine with Dependency Injection frameworks for advanced scenarios.
- Useful when working with Flutter platform-specific widgets or plugin adapters.
Summary Table
| Attribute | Factory Method Pattern |
|---|---|
| Purpose | Flexible object creation |
| Easy in Dart? | Yes (factory constructor supported) |
| Common Use Cases | Widget factories, platform adapters |
| Useful in Flutter? | Absolutely |



