Factory pattern

From wikinotes
Revision as of 22:39, 26 November 2022 by Will (talk | contribs)

A class/method responsible for choosing/instantiating a class for you.


Basics

Given classes Cat, Dog that implement interface Animal,
We want a factory that chooses the desired pet.

module Animal
  interface!

  sig { abstract.returns(String) }
  def speak; end
end

class Cat
  include Animal

  sig { override.returns(String) }
  def speak
    "meow"
  end
end

class Dog
  include Animal

  sig { override.returns(String) }
  def speak
    "woof"
  end
end
class PetFactory
  def from(interests)
    return Cat.new if interests.include?(:homebody)

    Dog.new
  end
end

Subclass Hooks

If your language supports subclass hooks, even without eager loading you can register concretions automatically.
reusing the previous example:


class AnimalBase
  # when inheritance is read, is registered with the superclass's '@register'
  def self.inherited(concretion)
    register(concretion)
  end

  def self.register(concretion)
    @register << concretion
  end

  def self.from(interests)
    @register.find { |concretion| concretion.handles?(interests) }
  end
end
class Cat < AnimalBase
  include Animal

  def speak
    "meow"
  end

  def self.handles?(interests)
    interests.include?(:homebody)
  end
end

class Dog < AnimalBase
  include Animal

  def speak
    "woof"
  end

  def self.handles?(interests)
    !interests.include?(:homebody)
  end
end
class AnimalBase
  def self.from(interests)
    AnimalBase.from(interests)
  end
end