Rubyによるデザインパターンまとめ : adapter
利用する場面
やりとりをさせたい複数のオブジェクトの間でインターフェースが噛み合わないとき。 一方または両方のクラスのインターフェースを変更してもよいが、インターフェースを揃える役割をadapterに担わせて解決することができる。
その他
- 呼び出される側をいじることに注意する。
- 永続的にorその場限りで必要なメソッドをもたせてもよいのでは?と思ったら、まさしくその説明がでてきた。
- つまり、クラスの上書きor特異メソッド。
- 「アダプタではいくらかの複雑さと引き換えにカプセル化を守ることができます。クラスの変更ではいくらかの単純化と引き換えに、内部をいじくり回すコストがかかります。」
サンプル
犬は人間の挨拶に答えられないが、adapterを使って答えられるようにしてみる。
class Creature attr_reader :name def initialize(name) @name = name end end class Man < Creature def greet(man) p "hello, #{man.name}" man.reply(self) end def reply(man) p "hello, #{man.name}" end end class Dog < Creature def bark p "bowwow" end end taro = Man.new(:taro ) jiro = Man.new(:jiro ) pochi = Dog.new(:pochi) taro.greet(jiro) # => "hello, jiro", "hello, taro" taro.greet(pochi) # => "hello, pochi", (NoMethodError) class DogAdapter attr_reader :name def initialize(dog) @dog = dog @name = dog.name end def reply(man) p "hello, #{man.name}" end end speakable_pochi = DogAdapter.new(pochi) taro.greet(speakable_pochi) # => "hello, pochi", "hello, taro"
特異メソッドを使って、ポチだけが話せるようにしてみる。
class << pochi def reply(man) p "hello, #{man.name}" end end taro.greet(pochi) # => "hello, pochi", "hello, taro"
ちなみに特異メソッドは以下の書き方でも定義できる。
def pochi.reply(man) p "hello, #{man.name}" end taro.greet(pochi) # => "hello, pochi", "hello, taro"