The Factory Method Pattern

The factory method is a creational design pattern. It’s intent is to create instances of classes without having to explicitly call new on them.

Why would you want to do this?

The problem this pattern tries to solve is to have a mechanism for creating an instance of a class without knowing what type will be created.

The GOF defines the gactory method as:

“Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.”

Example

To be the factory method, it has to handle the actual creation of the new instance, if it doesn’t create it, it may be the template pattern or something else.

This example will try to be very descriptive:

class Transport
  def get_to_location
    # the get_new_vehicle method
    # is our factory method, which will
    # determine which vehicle to create
    vehicle = get_new_vehicle
    vehicle.drive # each vehicle class implements the drive method
  end

  def get_new_vehicle
    raise "abstract method, implement in children class"
  end

A derivative class of the Transport class will implement the factory method get_new_vehicle:

class WilburTransport < Transport
  # Wilbur wishes he drives a Ferrari :-)
  def get_new_vehicle
    Ferrari.new
  end
end

class publicTransport < Transport
  def get_new_vehicle
    Bus.new
  end
end

Some notes about the Factory Pattern

  1. You should use the factory pattern when you have a class that does not know what objects it should create, or when you want the subclasses to determine the type of objects that should be created.
  2. It helps with the single responsibility principle by moving the creation of objects to one part of the system making it easier to maintain.
  3. Helps you conform with the open/close principle in that you can add new types of objects without breaking existing functionality.

On design patterns

Very often I find fellow developers struggling with design patterns. They get the question in a job interview or they need them in their daily life to build better system designs. Design patterns are a very important piece in the developers toolchain. I will explain about them and how to use them.

Design patterns are solutions to frequent problems in software design. They are kind of like a blueprint that you can customize for a recurring design problem in your code.

You cannot take a pattern and copy it from somewhere else, they are more like a concept for general problems. You can follow the details of the pattern and change it to suit you specific scenario.

Patterns are usually confounded with algorithms because they both describe typical solutions to general problems. An algorithm expresses the detailed steps to solve a problem. A pattern is a higher level description of a design solution. You can use the same pattern in different projects and the code can be different.

Design patterns are classified by their intent and purpose as:

Creational Design Patterns

Creational patterns provides mechanisms for creating objects and reuse existing code.

Structural Design Patterns

Structural patterns explain how to assemble objects and classes into larger structures and maintining this structures flexible and efficient.

  • Adapter
  • Bridge
  • Composite
  • Decorator
  • Facade
  • Flyweight
  • Proxy

Behavioral Design Patterns

Behavioral patterns are concerned with algorithms and responsibilities between objects.

  • Chain of responsibility
  • Command
  • Iterator
  • Mediator
  • Memento
  • Observer
  • State
  • Strategy
  • Template Method
  • Visitor

Using Service Objects in Ruby on Rails

Once an application reaches certain size, questions about architecture begin to appear. Rails follows a Model View Controller organization and basic rules exist for clean code:

  • No Fat Models – don’t allow them to get bloated
  • Keep views dumb – don’t put any logic in there
  • Keep controllers skinny – don’t put too much there

And it raises the first question: Where do I put all that code?

Introducing service objects

Service objects can be a class or a module in Ruby that perform an action and can help take out logic from other areas of the MVC structure. For a simple example, let’s say we have a controller like this:

class PostsController < ApplicationController
  def create
    @title = params[:title]
    @content = params[:content]
    @post = Post.new(title: @title, content: @content)
    if @post.save
      flash.notice = 'Post saved'
      render @post
    else
      flash.alert = flash_error_message(@post)
      redirect_to :new
    end
  end
end

Extracting some of this into a service object is easy once you understand the design pattern.

  • create a services folder in the Rails’ app folder
  • create the service object file, in this example create_post.rb
  • extract the functionality to the CreatePost class/module
  • reload the Rails app and try it

Service objects as modules

Using a module approach I created a service that looks very much like a factory design pattern:

module CreatePost
  class << self
    def execute(params)
      title = params[:title]
      content = params[:content]
      post = Post.new(title: title, content: content)
    end
  end
end

Which in turn made the controller a lot more manageable:

class PostsController < ApplicationController
  def create
    @post = CreatePost.execute(params)
    if @post.save
      flash.notice = 'Post saved'
      render @post
    else
      flash.alert = flash_error_message(@post)
      redirect_to :new
    end
  end
end

Service objects as classes

In some cases we need to store instance variables and other methods, if so, we use classes. Using a class, our code could be rewritten as:

class CreatePost
  def initialize(params)
    @title = params[:title]
    @content = params[:content]
  end

  def call
    Post.new(title: @title, content: @content)
  end
end

The code of the controller would be:

class PostsController < ApplicationController
  def create
    @post = CreatePost.new(params).call
    if @post.save
      flash.notice = 'Post saved'
      render @post
    else
      flash.alert = flash_error_message(@post)
      redirect_to :new
    end
  end
end

Organizing service objects with modules

When we start using services our services folder tends to grow a lot. We can manage this growth by creating a modular structure using folders and modules.

The services folder can reflect the variety of service objects and it’s different uses in our app. We group them in namespaces using Ruby modules.

module Post
  module Build
    def self.call(params)
      title = params[:title]
      content = params[:content]
      Post.new(title: title, content: content)
    end
  end
end

To achieve this we have to place them in folders that reflects our module structure to let Rails load them.

services/post/build.rb
services/post/update.rb
services/comments/build.rb
...

This way our use of service objects can scale with the growth of our app.