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:
- Define the Product Interface:
# Product interface
class Product
def display
raise NotImplementedError, 'Subclasses must implement the display method'
end
end
- Implement Concrete Products:
# Concrete product
class ConcreteProduct < Product
def display
puts 'Displaying concrete product.'
end
end
- 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
- Implement Concrete Creator:
# Concrete creator with specific factory method implementation
class ConcreteCreator < Creator
def create_product
ConcreteProduct.new
end
end
- Client Code:
# Client code using the Factory Method Pattern
creator = ConcreteCreator.new
creator.use_product
Abstract Factory Pattern:
- 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
- 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
- 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
- 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
- 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:
-
Number of Products:
- Factory Method Pattern: Involves creating a single product.
- Abstract Factory Pattern: Involves creating families of related products.
-
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.
-
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.