Tbpgr Blog

Employee Experience Engineer tbpgr(てぃーびー) のブログ

Ruby | Adapter Pattern

概要

Adapter Pattern

詳細

Adapter Patternは、既存のインターフェースと新たなインターフェースの橋渡しを行います。

サンプル仕様

あるサービスを提供するシステムがあります。
複数の利用者がサービスを呼び出します。

1次開発ではサービスはargs引数のみを用意していました。
2次開発でoptionも受け取るようにします。
しかし、すでにサービスが提供されておりしばらくの間は古いインターフェースも残しておく必要があります。
そのためにアダプターを用意します。

3次開発では、旧サービスの利用を廃止してアダプタとして呼び出していた処理も
新たな処理内容に改修します。

サンプル アダプター適用前(1次開発)

class SomeOldService
  def bad_name_service1(args)
    "use old service1"
  end
end

class SomeOldAction1
  def action
    SomeOldService.new.bad_name_service1 "message from action1"
  end
end

class SomeOldAction2
  def action
    SomeOldService.new.bad_name_service1 "message from action2"
  end
end

puts SomeOldAction1.new.action
puts SomeOldAction2.new.action

出力

use old service1
use old service1

サンプル アダプター適用後(2次開発)

アダプターによって

class SomeOldService
  def bad_name_service1(args)
    "use old service1"
  end
end

class SomeNewService
  # SomeOldService#bad_name_service1への
  def good_name_service1(args)
    SomeOldService.new.bad_name_service1(args)
  end

  def good_name_new_service2(args)
    "use new service2 with option"
  end
end

class SomeOldAction1
  def action
    SomeOldService.new.bad_name_service1 "message from action1"
  end
end

class SomeOldAction2
  def action
    SomeOldService.new.bad_name_service1 "message from action2"
  end
end

class SomeNewAction3
  def action
    SomeNewService.new.good_name_service1 "message from action3"
  end
end

class SomeNewAction4
  def action
    SomeNewService.new.good_name_new_service2 "message from action4"
  end
end

[SomeOldAction1.new, SomeOldAction2.new, SomeNewAction3.new, SomeNewAction4.new].each { |v|puts v.action }

出力

use old service1
use old service1
use old service1
use new service2

サンプル 旧IF廃止(3次開発)

class SomeNewService
  def good_name_service1(args, option)
    "use new service1 with option"
  end

  # 新規サービス
  def good_name_new_service2(args, option)
    "use new service2 with option"
  end
end

class SomeOldAction1
  def action
    SomeNewService.new.good_name_service1 "message from action1", "option"
  end
end

class SomeOldAction2
  def action
    SomeNewService.new.good_name_service1 "message from action2", "option"
  end
end

class SomeNewAction3
  def action
    SomeNewService.new.good_name_service1 "message from action3", "option"
  end
end

class SomeNewAction4
  def action
    SomeNewService.new.good_name_new_service2 "message from action4", "option"
  end
end

[SomeOldAction1.new, SomeOldAction2.new, SomeNewAction3.new, SomeNewAction4.new].each { |v|puts v.action }

出力

use new service1 with option
use new service1 with option
use new service1 with option
use new service2 with option