- Published on
Design Patterns: Factory
- Authors
- Name
- Loi Tran
Introduction
The Factory 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. It abstracts the instantiation process, letting the client code rely on a common interface rather than concrete implementations, which promotes flexibility and maintainability.
Purpose
Creates objects without specifying the exact class of the object that will be created.
Use Cases
Object creation where subclasses decide which class to instantiate.
from abc import ABC, abstractmethod
# Abstract Product
class Shape(ABC):
@abstractmethod
def draw(self):
pass
# Concrete Products
class Circle(Shape):
def draw(self):
return "Drawing a Circle"
class Square(Shape):
def draw(self):
return "Drawing a Square"
# Factory
class ShapeFactory:
@staticmethod
def get_shape(shape_type):
if shape_type == "circle":
return Circle()
elif shape_type == "square":
return Square()
else:
raise ValueError("Unknown shape type")
# Usage
factory = ShapeFactory()
shape1 = factory.get_shape("circle")
shape2 = factory.get_shape("square")
print(shape1.draw()) # Drawing a Circle
print(shape2.draw()) # Drawing a Square
// Abstract Product is not enforced in JS, but we define concrete products
class Circle {
draw() {
return "Drawing a Circle";
}
}
class Square {
draw() {
return "Drawing a Square";
}
}
// Factory
class ShapeFactory {
static getShape(shapeType) {
if (shapeType === "circle") {
return new Circle();
} else if (shapeType === "square") {
return new Square();
} else {
throw new Error("Unknown shape type");
}
}
}
// Usage
const shape1 = ShapeFactory.getShape("circle");
const shape2 = ShapeFactory.getShape("square");
console.log(shape1.draw()); // Drawing a Circle
console.log(shape2.draw()); // Drawing a Square
// Abstract Product
abstract class Shape {
String draw();
}
// Concrete Products
class Circle implements Shape {
String draw() => "Drawing a Circle";
}
class Square implements Shape {
String draw() => "Drawing a Square";
}
// Factory
class ShapeFactory {
static Shape getShape(String shapeType) {
if (shapeType == "circle") {
return Circle();
} else if (shapeType == "square") {
return Square();
} else {
throw ArgumentError("Unknown shape type");
}
}
}
// Usage
void main() {
var shape1 = ShapeFactory.getShape("circle");
var shape2 = ShapeFactory.getShape("square");
print(shape1.draw()); // Drawing a Circle
print(shape2.draw()); // Drawing a Square
}
# Abstract Product is not enforced in Ruby, but we define concrete products
class Circle
def draw
"Drawing a Circle"
end
end
class Square
def draw
"Drawing a Square"
end
end
# Factory
class ShapeFactory
def self.get_shape(shape_type)
case shape_type
when "circle"
Circle.new
when "square"
Square.new
else
raise "Unknown shape type"
end
end
end
# Usage
shape1 = ShapeFactory.get_shape("circle")
shape2 = ShapeFactory.get_shape("square")
puts shape1.draw # Drawing a Circle
puts shape2.draw # Drawing a Square
Conclusion
The Factory pattern is useful when your code needs to create objects dynamically without hard-coding their concrete classes. It simplifies object creation, encourages loose coupling, and makes it easier to introduce new types of objects or modify creation logic without affecting the client code. Common use cases include creating different shapes, database connections, or user interface components based on configuration or runtime conditions.