Factory Method Design Pattern in Ruby

1. Definition

The Factory Method Design Pattern defines an interface for creating objects but allows subclasses to alter the type of objects that will be created. Instead of calling a constructor directly, a factory method is used to produce instances of a class.

2. Problem Statement

Consider a situation where a class cannot anticipate the type of objects it needs to create, or when a class wants its subclasses to specify the objects it creates. A direct instantiation using constructors can become complex and not scalable.

3. Solution

The Factory Method pattern suggests providing a separate method for object creation and pushing this responsibility to subclasses, enabling them to redefine and adjust the type of created objects.

4. Real-World Use Cases

1. GUI libraries where each OS provides a different implementation of a button or window.

2. Payment gateway integration where each provider has a different process.

3. Frameworks that need to instantiate classes, but the exact classes might not be known until runtime.

5. Implementation Steps

1. Declare a factory method in a base class with its default implementation or make it abstract.

2. Create concrete subclasses that override this factory method to return an instance of their choice.

6. Implementation in Ruby

# Base class with a factory method class Creator def factory_method raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'" end def operation product = factory_method "Base operation with: #{product.operation}" end end # Concrete creators that override the factory method class ConcreteCreatorA < Creator def factory_method ConcreteProductA.new end end class ConcreteCreatorB < Creator def factory_method ConcreteProductB.new end end # Product interface class Product def operation raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'" end end # Concrete products class ConcreteProductA < Product def operation 'Result from ConcreteProductA' end end class ConcreteProductB < Product def operation 'Result from ConcreteProductB' end end # Client code creator1 = ConcreteCreatorA.new puts creator1.operation creator2 = ConcreteCreatorB.new puts creator2.operation 

Output:

Base operation with: Result from ConcreteProductA Base operation with: Result from ConcreteProductB 

Explanation:

1. The Creator class has a factory_method that serves as a placeholder for creating Product objects.

2. The ConcreteCreatorA and ConcreteCreatorB subclasses provide their implementation of the factory_method, determining what product to instantiate.

3. The client code interacts with the factory method through the operation method of the Creator class. It remains unaware of the concrete classes used, ensuring the decoupling of client code from class instantiation.

7. When to use?

Use the Factory Method pattern when:

1. A class can't anticipate the class of objects it must create.

2. Subclasses are responsible for implementing the factory method to produce objects.

3. You want to provide a library of products and expose the creation logic to clients, but keep the main code decoupled from these classes.


Comments