OOP Design Patterns with Ruby: Adapter

Keenan Jones
3 min readAug 28, 2020

In 1994, the “Group of Four”, Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides, wrote “Design Patterns: Elements of Reusable Object-Oriented Software”. These four saw common patterns emerge from their experience with Java and C++. These patterns can be adapted to any Object Orientated Programming language(O.O.P). Today, we’re experiencing these patterns through Ruby.

The first pattern we’re going to visit is the Adapter pattern. The Adapter pattern, “allows for two incompatible classes to work together by wrapping an interface around one of the existing classes”. An interface is what a ruby object has the ability to do otherwise known as its methods and attributes. The adapter pattern requires three classes: the target, the adapter and the adaptee.

Let’s break down each of these components.

The adaptee is an existing class that we want the target to adapt towards. This is an electrical outlet with three prongs. Or in our case a Dragon class. Everything inside of the dragon class is its interface

class Dragon def initialize(name)  @name = name end def fire_blast  print( @name + " does 20pts fire damage") endend

The target is the class that we wish to adapt or a two prong electrical outlet. The Monster class.

class Monster def initialize(adapter)  @adapter = adapter end def attack  @adapter.attack endend

This class accepts an adapter when an instance is created. An adapter translates the adaptee method to the target methods. The attack method wraps the dragon’s fire blast method.

class DragonAdapterdef initialize(dragon)@dragon = dragonend
def attack@dragon.fire_blastendend

Now, the result of this pattern allows for us to call attack on an instance of a dragon class.

dragon = Dragon.new("Dragonite")dragon_adapter = DragonAdapter.new(dragon)dragonite = Monster.new(dragon_adapter)dragonite.attack 
//"Dragonite does 20pts fire damage"

Now the flexibility part! So now because we have Monster class that accepts an adapter we can continue to use the monster class. Let’s create another adapter and another adaptee.

class BlobAdapter def initialize(color)   @color = color end def attack   @color.absorb endendclass Blob def initialize(color)   @color = color end def absorb   print("The " + @color + " blob does 5pts damage and recover 10pts of health") endend
//Now can still use the Monster class for the blob. blob = Blob.new('Green')blob_adapter = BlobAdapter.new(blob)green_blob = Monster.new(blob_adapter)green_blob.attack//output "The Green blob does 5pts damage and recover 10pts of health"

Keep the pattern in mind for refactoring legacy code. An Adapter is recognizable it calls a different class’ methods. When a adapter receives a call, it translates its parameters to the appropriate format and then directs the call to one or many of its wrapped objects.

Thanks for your time. I reference the refactoring guru. D. L. Jerome on Medium and don’t forget to read Design Patterns: Elements of Reusable Object-Oriented Software by the group of four writing the article. I highly recommend reading these.

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Keenan Jones
Keenan Jones

No responses yet

Write a response