Adapter

The Adapter pattern is one of those patterns that requires little imagination to figure out what they do.

First off, let’s see the definition courtesy of GoF:

Convert the interface of a class into another interface clients expect.

Adapter lets classes work together that couldn’t otherwise because of incompatible interfaces.

Let’s see some code:

class Client
  def initialize(target)
    @target = adapter
  end

  def do_work
    # do hard work …
    @target.complex_operation
    # ...
  end
end

class Target
  def complex_operation
    # la la la ...
  end
end

Here’s the story:

Normally the Client would be expecting that the target be able to do_work without a hitch:

client = Client.new(Target.new)
client.do_work

One fine day, your boss comes over, and shows you this class, and tells you that SomeOtherTarget must work with Client:

class SomeOtherTarget
  def trivial_operation
    # oh no! different method name…
  end
end

Obviously, this won’t work, because SomeOtherTarget does not have the complex_operation method that the Client expects:

client = Client.new(SomeOtherTarget.new)
client.do_work # DOES NOT WORK

Plugging in the Adapter

We need some way to bridge this difference in interfaces. How do we somehow connect Client‘s expectation of a complex_operation method with SomeOtherTarget’s trivial_operation ?

Here’s the Adapter class to the rescue:

class Adapter 
  def initialize(adaptee)
    @adaptee = adaptee
  end

  def complex_operation
    @adaptee.trivial_operation
  end
end

And with this bit of indirection, Client can happily use SomeOtherTarget:

client = Client.new(Adapter.new(SomeOtherTarget.new))
client.do_work # DOES NOT WORK

Notice how now the Adapter object takes the place of the @target instance variable of Client. The Adapter object now becomes the middleman/wrapper/translator. This is composition at work!

2 Flavors of Adapters: Object & Class

Now, if you check out the Wikipedia entry you will see the 2 kinds of Adapters - Class and Object adapters.

Object Adapter

Object adapter (Credits: Wikipedia)

Class Adapter

Class adapter (Credits: Wikipedia)

So what’s the difference?

I don’t know about you, but when I first saw both UML diagrams, my eyes glazed. The key here to to focus on the differences.

The Object Adapter uses composition. Notice that the Adapter has an +adaptee field. The Adapter class has to use the Adaptee class, and that’s essentially composition.

The Class Adapter uses multiple inheritance (that’s the hollow triangular arrows pointing upwards). Frankly, I don’t know too much about multiple inheritance, and in general, unless you’re a C++ programmer (I’m sorry), you probably won’t need this.

Conclusion: Stick to the Object Adapter.

In the next post, I will look at the Proxy pattern. Thanks for reading!

References

Olsen, R. (2008) Design patterns in Ruby. Upper Saddle River, NJ: Addison-Wesley, p.163-174.