Decorator Pattern

Created: 13 August 2012  Modified:

Attaches additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality
Head First Design Patterns

This design pattern would be useful when you consider the attributes of of a Super Hero. A hero can have a normal strength and yet have a power that enhances his strength beyond human norms. Also heros can achieve greater strength via mechanical or pharmaceutical means.

This is achieved by the decorator objects swallowing the core object and other decorator objects. This swallowing is called composition. Any object is then accessible as long as it is part of the composition. This access is usually defined through abstraction or an interface. Through the interface the innermost object to the outermost can make calls through the agreed method to the other objects.

Decorator Pattern Encapsulation
Decorator Pattern Encapsulation

Taking this basic concept we can then build the class structure below. The classes in italics are abstract.

Decorator Pattern Class
Decorator Pattern Class

Finally we can build these classes and objects in Ruby as seen in the following code. One difference between the code and the class diagram is that Ruby doesn’t need to define the abstract classes. It more or less defines an interface using a module.

Decorator-Pattern.rb

module HeroDecorator
  def initialize(heroDecorated)
    @heroDecorated = heroDecorated
  end
end


class Hero
  def name
    "Bob"
  end

  def description
    "He is really strong"
  end

  def strength
    40
  end

  def intelligence
    10
  end
end


class CombatDrugs
	include HeroDecorator
  def strength
    @heroDecorated.strength() + 40
  end

  def intelligence
    @heroDecorated.intelligence() + -5  
  end
end


class SuperStrength
  include HeroDecorator
  def strength
    @heroDecorated.strength() + 40
  end

  def intelligence
    @heroDecorated.intelligence() + 0  
  end
end

bob = CombatDrugs.new(SuperStrength.new(Hero.new()))

puts "Strength=" + bob.strength.to_s
puts "Intelligence=" + bob.intelligence.to_s
tags:
   Less Is More