These GoF patterns are the Factory Method pattern and the Abstract Factory pattern.

The Factory Method pattern involves the application of the Template Method pattern to object creation. True to its Template Method roots, this pattern says to just leave the “which class” question to be answered by a subclass.

While the GoF concentrated on inheritance-based implementations of their factories, we can get the same results with much less code by taking advantage of the fact that in Ruby, classes are just objects. In Ruby we can look up classes by name, pass them around, and store them away for future use.

The Abstract Factory pattern comes into play when you want to create compatible sets of objects. Not every object needs to be produced by a factory. In fact, most of the time you will want to create most of your objects with a simple call to MyClass.new.

The Template Method Strikes Again

The GoF called this technique of pushing the “which class” decision down on a subclass the Factory Method pattern. We start by building a generic base class, a class that is generic in the sense that it does not make the “which class” decision.

Screenshot 2023-03-29 at 15.32.45.png

On the one hand, we have the creators, the base and concrete classes that contain the factory methods. On the other hand, we have the products, the objects that are being created. In our pond example, the creator is the Pond class, and the specific types of ponds (like DuckPond and FrogPond) are the concrete creators; the products are the Duck and Frog classes. While Figure 13-1 shows the two products sharing a common base class (Product), our Duck and Frog are not actually blood relatives: They simply share a common type because they implement a common set of methods.

Parameterized Factory Methods

Suppose your pond simulation is so popular that your users start asking you to simulate plants as well as animals. So you wave your magic code wand and come up with a couple of plant classe

Screenshot 2023-03-29 at 15.52.43.png

Classes Are Just Objects

A way to simplify our Abstract Factory pattern implementation: We can make it a bundle of class objects, with one class for each product (as a parameter). This is exactly the same “classes are just objects” insight that helped us simplify the Factory Method pattern.

class OrganismFactory
  def initialize(plant_class, animal_class)
    @plant_class = plant_class
    @animal_class = animal_class
  end

  def new_animal(name)
    @animal_class.new(name)
	end

  def new_plant(name)
    @plant_class.new(name)
	end 
end

# Then, no need JungleOrganismFactory or PondOrganismFactory anymore
jungle_organism_factory = OrganismFactory.new(Tree, Tiger)
pond_organism_factory = OrganismFactory.new(WaterLily, Frog)
jungle = Habitat.new(1, 4, jungle_organism_factory)
jungle.simulate_one_day
pond = Habitat.new( 2, 4, pond_organism_factory)
pond.simulate_one_day

The code above shows a class-based abstract factory. Instead of having several different abstract factory classes, one class for each set of things that the factory needs to produce, we can have just one factory class that stores the class objects of the things that it needs to produce such as plant_class and animal_class.

Leveraging the Name