Post

Creational Design Patterns: Abstract Factory Method

Purpose

The Abstract Factory pattern is like a blueprint for creating different “families” of objects without telling the program exactly which specific objects to create. Imagine it as a factory that makes a set of related products, like a car factory that makes engines and tires. You can ask the factory for a car, and it will give you the right kind of engine and tires without you needing to know how they’re made.

In short, this pattern helps you:

  • Create groups of related objects (like car parts or motorcycle parts).
  • Change the specific parts being created without modifying your code everywhere.
  • Ensure that the parts are compatible with each other.

Explanation

Let’s say we have two types of vehicles: Cars and Motorcycles. Each vehicle needs two parts: an Engine and Tires. But the car and the motorcycle have different engines and tires (e.g., car engines are more powerful, and motorcycle tires are made for different terrains).

Using the Abstract Factory pattern, we would create two factories:

  • Car Factory: This factory knows how to make a car engine and car tires.
  • Motorcycle Factory: This factory knows how to make a motorcycle engine and motorcycle tires.

Now, you (as the programmer) don’t need to know all the details about how engines or tires are made. You just ask the right factory for the parts. The factory will give you the correct parts that fit together.

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 Parts(Products)

First, we define the vehicle parts. There are two parts: the Engine and Tires.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Abstract class for Engine
class Engine
  def specs
    raise NotImplementedError, "This method should be overridden"
  end
end

# Abstract class for Tires
class Tires
  def specs
    raise NotImplementedError, "This method should be overridden"
  end
end

Step 2: Create Concrete Parts

Now, we define specific parts for cars and motorcycles.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# Car-specific parts
class CarEngine < Engine
  def specs
    "Car engine: 200 horsepower"
  end
end

class CarTires < Tires
  def specs
    "Car tires: Smooth road tread"
  end
end

# Motorcycle-specific parts
class MotorcycleEngine < Engine
  def specs
    "Motorcycle engine: 100 horsepower"
  end
end

class MotorcycleTires < Tires
  def specs
    "Motorcycle tires: Rough off-road tread"
  end
end

Step 3: Create the Factory Method

Next, we create the factories that produce the correct parts.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# Abstract factory class
class VehicleFactory
  def create_engine
    raise NotImplementedError, "This method should be overridden"
  end

  def create_tires
    raise NotImplementedError, "This method should be overridden"
  end
end

# Car Factory
class CarFactory < VehicleFactory
  def create_engine
    CarEngine.new
  end

  def create_tires
    CarTires.new
  end
end

# Motorcycle Factory
class MotorcycleFactory < VehicleFactory
  def create_engine
    MotorcycleEngine.new
  end

  def create_tires
    MotorcycleTires.new
  end
end

Step 4: Using the Factory Method

Finally, we use these factories to create vehicles without knowing the details.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def build_vehicle(factory)
  engine = factory.create_engine
  tires = factory.create_tires

  puts "Engine: #{engine.specs}"
  puts "Tires: #{tires.specs}"
end

car_factory = CarFactory.new
puts "Building a car:"
build_vehicle(car_factory)

puts "-------------------"

motorcycle_factory = MotorcycleFactory.new
puts "Building a motorcycle:"
build_vehicle(motorcycle_factory)

Output:

1
2
3
4
5
6
7
Building a car:
Engine: Car engine: 200 horsepower
Tires: Car tires: Smooth road tread
-------------------
Building a motorcycle:
Engine: Motorcycle engine: 100 horsepower
Tires: Motorcycle tires: Rough off-road tread

Conclusion

The Abstract Factory pattern allows you to build families of related objects (like vehicle parts) without worrying about the specifics of how those objects are created. It’s like giving an order to a specialized factory and getting the right parts, whether for a car, motorcycle, or any other vehicle!

Cheers :)

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

Comments powered by Disqus.