DEV Community

rubyhub.io
rubyhub.io

Posted on • Originally published at Medium

Design Patterns in Ruby | FLYWEIGHT 💿

Overview

Flyweight is a structural design pattern that allows you to reduce RAM consumption by sharing states between similar objects.

It is one of the lesser-used design patterns because of its use. With today’s computing power, we rarely think about the performance of our computers

Image description

Coding Example

Let’s assume we have a Canvas on which we want to draw. In order to draw something, we need to put some Color in the right places. So we’ll create a Color class that takes a hexadecimal value as the only attribute.

class Color
  attr_reader :hex

  def initialize(hex)
    @hex = hex
  end
end
Enter fullscreen mode Exit fullscreen mode

Now let’s imagine we want to cover the entire canvas with a resolution of 1000 x 1000 in black.

class Canvas 
  def draw(x:, y:, color:)
    # Draw color on provided coordinates
  end
end

canvas = Canvas.new

1000.times do |x|
  1000.times do |y|
    canvas.draw(x: x, y: y, color: Color.new('#000000'))
  end
end
Enter fullscreen mode Exit fullscreen mode

A canvas created in this way will create as many as a million objects of the Color class. However, we can avoid this with the Flyweight pattern, which allows us to do this using only one object.

So now let’s create a ColorFactory class that will be responsible for color distribution.

class ColorFactory
  attr_reader :colors

  def initialize
    @colors = {}
  end

  def find_color(hex)
    if colors.has_key?(hex)
      color = colors[hex]
    else
      color = Color.new(hex)
      colors[hex] = color
    end

    color
  end
end
Enter fullscreen mode Exit fullscreen mode

This class will store the already created colors, but not in the form of an array, but in the form of a hash. The find_color method will check if a given color already exists and will create a new object only if it has not been created before and add it to the colors hash.

Now using the factory class we are able to create an all-black canvas using only one object.

class Canvas
  attr_reader :color_factory

  def initialize
    @color_factory = ColorFactory.new
  end

  def draw(x:, y:, color:)
    color = color_factory.find_color(color)

    # Draw color on provided coordinates
  end
end

canvas = Canvas.new

1000.times do |x|
  1000.times do |y|
    canvas.draw(x: x, y: y, color: '#000000')
  end
end
Enter fullscreen mode Exit fullscreen mode

Top comments (0)