Adapterパターンとは
- 特徴
- レガシーなクラスを変更せずにそのメソッドを使うことができます
- 異なるクラスについて、同じような処理をしたい時に共通のインターフェイスで実行できます
ActiveRecordでもデータベースエンジン毎のコネクションにAdapterパターンが使われたりもしています。
構成は以下のような形です。
- 利用者(Client):ターゲットのメソッドを呼び出す
- ターゲット(Target):インターフェースを規定
- アダプタ(Adapter):アダプティのインターフェースを変換してターゲット向けのインターフェースを提供
- アダプティ(Adaptee):実際に動作する既存のクラス
今回はシンプルな例を挙げたいと思います。
具体例
clientからはTargetクラスにあるrequestメソッドを呼び出すことができるが、そのメソッド名を変えずにAdapteeクラスのold_requestメソッドを呼び出したいとします。
それでは実装に入ります。
Targetクラスはrequestメソッドを持っています。
class Target
def request
'新しいクラスです'
end
end
ここに古いクラスがあり、old_requestメソッドを持っているとします。
class Adaptee
def old_request
'古いクラスです'
end
end
client_codeメソッドではTargetクラスのインスタンスを受け取り、requestメソッドを呼び出しています。
ここで古いクラスのold_requestをclient_codeメソッドで呼び出したかった時にAdapterが力を発揮します。
def client_code(target)
puts target.request
end
target = Target.new
client_code(target)
# => '新しいクラスです'
Adapterクラスを定義しました。
ここではTargetクラスで定義されているrequestメソッドを上書きし、中では古いクラスであるAdapteeのold_requestを呼び出します。
これによって、requestメソッドを経由してold_requestメソッドを呼び出していることになります。
class Adapter < Target
def initialize(adaptee)
@adaptee = adaptee
end
def request
@adaptee.old_request
end
end
TargetクラスのインスタンスとAdapterクラスのインスタンスで比べてみるとわかりやすいです。
Adapterをclient_codeメソッドに渡すことで、requestメソッドによってold_requestメソッドを呼ぶことができています。
古いクラスをrequestメソッドに合わせることもなく、client_codeも変更せずに済みました!
def client_code(target)
puts target.request
end
target = Target.new
client_code(target)
# => '新しいクラスです'
adapter = Adapter.new(Adaptee.new)
client_code(adapter)
# => '古いクラスです'
参考
Adapter in Ruby
Rubyによるデザインパターン5原則
アダプタ(Adapter) | Ruby デザインパターン