Design Patterns in Ruby | FLYWEIGHT

rubyhub.io
2 min readNov 18, 2022

--

Structural design pattern that allows you to reduce RAM consumption by sharing states between similar objects.

Overview

Flyweight 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

Photo by Kelly Sikkema on Unsplash

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

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

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(flyweight factory) 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

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

More reading

--

--

rubyhub.io

[🔴 100% Follow-Back 🔴] I'm Full Stack Developer with 5-years of experience working with Ruby on Rails, trying to share my knowledge with others.