The Abstract Factory Pattern and the Factory Method Pattern are both creational design patterns, but they serve different purposes. While the Factory Method Pattern deals with creating a single product, the Abstract Factory Pattern deals with creating families of related or dependent products. Let's delve into a detailed explanation using Ruby on Rails code, and we'll highlight the differences between the two patterns.

Factory Method Pattern:

  1. Define the Product Interface:
# Product interface
class Product
  def display
    raise NotImplementedError, 'Subclasses must implement the display method'
  end
end
  1. Implement Concrete Products:
# Concrete product
class ConcreteProduct < Product
  def display
    puts 'Displaying concrete product.'
  end
end
  1. Define the Creator Class with Factory Method:
# Creator class with factory method
class Creator
  def create_product
    raise NotImplementedError, 'Subclasses must implement the create_product method'
  end

  def use_product
    product = create_product
    product.display
  end
end
  1. Implement Concrete Creator:
# Concrete creator with specific factory method implementation
class ConcreteCreator < Creator
  def create_product
    ConcreteProduct.new
  end
end
  1. Client Code:
# Client code using the Factory Method Pattern
creator = ConcreteCreator.new
creator.use_product

Abstract Factory Pattern:

  1. Define Abstract Product Interfaces:
# Abstract product interfaces
class Button
  def display
    raise NotImplementedError, 'Subclasses must implement the display method'
  end
end

class TextBox
  def display
    raise NotImplementedError, 'Subclasses must implement the display method'
  end
end
  1. Implement Concrete Products for Each Interface:
# Concrete products for the first family
class LightButton < Button
  def display
    puts 'Displaying light button.'
  end
end

class LightTextBox < TextBox
  def display
    puts 'Displaying light text box.'
  end
end

# Concrete products for the second family
class DarkButton < Button
  def display
    puts 'Displaying dark button.'
  end
end

class DarkTextBox < TextBox
  def display
    puts 'Displaying dark text box.'
  end
end
  1. Define Abstract Factory Interface:
# Abstract factory interface
class UIFactory
  def create_button
    raise NotImplementedError, 'Subclasses must implement the create_button method'
  end

  def create_text_box
    raise NotImplementedError, 'Subclasses must implement the create_text_box method'
  end
end
  1. Implement Concrete Factories:
# Concrete factories implementing the abstract factory interface
class LightUIFactory < UIFactory
  def create_button
    LightButton.new
  end

  def create_text_box
    LightTextBox.new
  end
end

class DarkUIFactory < UIFactory
  def create_button
    DarkButton.new
  end

  def create_text_box
    DarkTextBox.new
  end
end
  1. Client Code:
# Client code using the Abstract Factory Pattern
def create_ui(factory)
  button = factory.create_button
  text_box = factory.create_text_box
  [button, text_box]
end

# Using the Light theme
light_factory = LightUIFactory.new
light_components = create_ui(light_factory)
light_components.each(&:display)

# Using the Dark theme
dark_factory = DarkUIFactory.new
dark_components = create_ui(dark_factory)
dark_components.each(&:display)

Key Differences:

  1. Number of Products:

    • Factory Method Pattern: Involves creating a single product.
    • Abstract Factory Pattern: Involves creating families of related products.
  2. Type of Interface:

    • Factory Method Pattern: Defines an interface for creating a single product.
    • Abstract Factory Pattern: Defines interfaces for creating families of related products.
  3. Usage:

    • Factory Method Pattern: Used when there's a single product and its creation can be delegated to subclasses.
    • Abstract Factory Pattern: Used when there are multiple families of related products and the system needs to be configured with one of these families.

In summary, the Factory Method Pattern is suitable for scenarios where there is a single product, and its creation is delegated to subclasses. On the other hand, the Abstract Factory Pattern is used when there are families of related products and the system needs to be configured with one of these families. Both patterns promote loose coupling and flexibility in object creation.