Adapter

  • class/object structural pattern

GoF definition (p. 139):

"Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces."

Can be implemented either using inheritance (class pattern) or compostion (object pattern); but I think composition should always be the preferred method.

Also known as the 'wrapper' pattern.

Pros:

  • Enforces a consistent interface between two disparate objects.
  • Separates interface from implementation.

Cons:

  • The adapter must necessarily be highly coupled to the adaptee.

Example

Adaptee:

We will use the Cipher module as the adaptee.

http://ruby-doc.org/stdlib-2.0/libdoc/openssl/rdoc/OpenSSL/Cipher.html

require 'openssl'

# Adapter:
# --------

class MessageEncrypter
  def initialize(cipher)
    # 'cipher' is the adaptee whose interface we will 'adapt'.
    # Note that we use dependency injection here, so
    # 'cipher' could be any object with the same interface.
    @cipher = cipher
    @key = cipher.random_key
    @init_vector = cipher.random_iv
  end

  # The public interface defined by this adapter:

  def encrypt(message)
    @cipher.encrypt
    parse_message(message)
  end

  def decrypt(message)
    @cipher.decrypt
    parse_message(message)
  end

  private

  def parse_message(message)
    @cipher.key = @key
    @cipher.iv = @init_vector
    @cipher.update(message) + @cipher.final
  end
end

Implementation:

cipher = OpenSSL::Cipher::AES256.new(:CFB)
encrypter = MessageEncrypter.new(cipher)

puts "Encrypting 'Hello, world.' =>"
encrypted_msg = encrypter.encrypt("Hello, world.")
puts "#{encrypted_msg}"
puts "Decrypting #{encrypted_msg} =>"
decrypted_msg = encrypter.encrypt(encrypted_msg)
puts "#{decrypted_msg}"

results matching ""

    No results matching ""