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 デザインパターン