Post

Creational Design Patterns: Factory Method

Purpose

The Factory Method is a design pattern that allows you to create objects without specifying the exact class. Instead of calling a constructor, you delegate object instantiation to a factory method. This decouples the client code from the concrete classes, increasing the system’s flexibility and scalability.

Explanation

In the Factory Method pattern, a class defines a method (the factory method) that subclasses can override to create objects of various types. The primary advantage of this pattern is that it allows you to follow the Open/Closed Principle: your code is open for extension but closed for modification. By introducing a factory method, you can add new types of objects without changing the code that uses them.

Ruby Example: Vehicle Factory

Let’s consider an example where we want to create different types of vehicles—Car, Truck, and Motorcycle. We can use the Factory Method pattern to create these vehicle objects.

Step 1: Define the Product Interface

First, we define a Vehicle as base class(or interface or abstract class in other languages, but in Ruby, we’ll use a base class with a method that subclasses need to implement).

1
2
3
4
5
class Vehicle
  def drive
    raise NotImplementedError, "This method must be implemented in a subclass"
  end
end

Step 2: Create Concrete Products

Next, we define the concrete classes that inherit from Vehicle. Each class will override the drive method.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Car < Vehicle
  def drive
    puts "Driving a car!"
  end
end

class Truck < Vehicle
  def drive
    puts "Driving a truck!"
  end
end

class Motorcycle < Vehicle
  def drive
    puts "Riding a motorcycle!"
  end
end

Step 3: Create the Factory Method

Now, we define a factory class with a factory method that will be responsible for creating instances of Vehicle. This method can be overridden in subclasses if needed.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class VehicleFactory
  def self.create(type)
    case type
    when :car
      Car.new
    when :truck
      Truck.new
    when :motorcycle
      Motorcycle.new
    else
      raise "Unknown vehicle type: #{type}"
    end
  end
end

Step 4: Using the Factory Method

Finally, we use the VehicleFactory to create vehicles without knowing the details of the class instantiation.

1
2
3
4
5
6
7
8
9
10
11
vehical_car = VehicleFactory.create(:car)
vehical_car.drive  
# Output: Driving a car!

vehicle_truck = VehicleFactory.create(:truck)
vehicle_truck.drive  
# Output: Driving a truck!

vehicle_motorcyle = VehicleFactory.create(:motorcycle)
vehicle_motorcyle.drive 
# Output: Riding a motorcycle!

Advantages of Factory Method Pattern

  • Encapsulation: The factory method encapsulates the instantiation logic, allowing the client code to remain clean and decoupled from concrete classes.
  • Flexibility: New vehicle types can be added by extending the factory without modifying the existing code.
  • Abstraction: Actual/Client code interacts with the ‘Vehicle’ interface rather than specific classes, which encourages loose coupling.

Conclusion

The Factory Method pattern is an effective technique for handling object generation in a flexible and maintainable manner. Using this technique in Ruby allows us to easily extend the system by adding additional vehicle kinds without changing the fundamental logic, guaranteeing that the code follows SOLID principles.

Cheers :)

This post is licensed under CC BY 4.0 by the author.

Comments powered by Disqus.