This post is part of a series of reviews on the book Design Patterns in Ruby. Check out the Introduction post for a full table of contents along with some generic principles regarding Design Patterns.

Decorators are basically objects that ride on top of other objects with the intent of adding some functionality to them.

More formally speaking, the object and its decorators share a same interface, but the decorators hold a reference to the original object and override the shared method with some new things.

With that said, let’s write a simple class that writes a sentence and some decorators to ‘decorate’ that sentence with more funcionality.

class Writer
	def write(sentence)
		puts sentence
	end
end

writer = Writer.new
writer.write('hi')

class TimeDecorator
	def initialize(writer)
		@writer = writer
	end

	def write(sentence)
		@writer.write(Time.now.to_s + ': '+ sentence)
	end
end

time_writer = TimeDecorator.new(Writer.new)
time_writer.write('hi')

class SizeDecorator
	def initialize(writer)
		@writer = writer
	end

	def write(sentence)
		@writer.write(sentence + " |size: #{sentence.size}|")
	end
end


big_object = SizeDecorator.new(TimeDecorator.new(Writer.new))
big_object.write('hi')

Since we’re basically incrementing behavior, we could take advantage of Ruby’s mixins support: modules. This way we can dynamically extend objects with any module:

class Writer
	def write(sentence)
		puts sentence
	end
end

writer = Writer.new
writer.write('hi')

module TimeDecorator
	def write(sentence)
		super(Time.now.to_s + ': '+ sentence)
	end
end

writer.extend TimeDecorator
writer.write('hi')

module SizeDecorator
	def write(sentence)
		super(sentence + " |size: #{sentence.size}|")
	end
end

writer.extend SizeDecorator
writer.write('hello')

The Ruby on Rails framework has a pretty cool implementation of the Decorator pattern with the method called alias_method_chain, where it takes a method and renames it with some new functionality.