GoFのデザインパターン(Design Pattern)のアダプタ(Adapter) をRubyによるサンプルコードで紹介します。
アダプタは既存のインタフェースとの橋渡しをするためのデザインパターンです。
アダプタは現実世界の変換コネクタのようなものです。直接つながらないコネクタと差込口であっても、それらの間を変換コネクタが結びつけます。コネクタと差込口にカスタマイズが不要な点がアダプタの利点です。
アダプタが利用される場面
Adapterパターンは次のような場面でよく使います。
関連性・互換性のないオブジェクト同士を結びつける必要がある 他のコンポーネントへの変更ができるようにする
アダプタの構成要素
アダプタの構成要素は次の4つです。
利用者(Client):ターゲットのメソッドを呼び出す ターゲット(Target):インターフェースを既定する アダプタ(Adapter):アダプティのインターフェースを変換してターゲット向けのインターフェースを提供 アダプティ(Adaptee):実際に動作する既存のクラス
サンプルソース
次のようなモデルを例にアダプタパターンを説明していきます。
Client: Printクラスを使う側 Printerクラス(Target):Clientが使っているメソッドを持つ print_weak: カッコに囲って文字列を表示する printer_strong: アスタリスクで囲って文字列を表示する OldPrinterクラス(Adaptee):既に存在していたオブジェクト show_with_paren: 記述を弱めて書く show_with_aster: 記述を強めて書く
ClientはPrinterクラスのメソッドを使うことはできますが、Oldprinterクラスはメソッドの名前/定義が異なるため、改造無しに使うことができません。そこでAdapterデザインパターンを適用してClientがOldPrinterクラスを使えるようにします。
まずは、Printerクラスを確認します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
次にOldPrinterクラスです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | |
このOldPrinterクラスのメソッドをClientが使えるPrinterクラスのインターフェースにするAdapterクラスを作成します。このクラスには、次の2つのメソッドを定義します。
* #print_weak OldPrinter#show_with_parenを呼び出す * #print_strong OldPrinter#show_with_asterを呼び出す
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
以上がソースコードです。
では結果を確認するために、ClientにTargetを動かしてもらいます。
1 2 3 4 5 6 7 | |
ClientはTargetのメソッドを呼び出しているだけですが、Adapterを介して接続したOldPrinterのメソッドにアクセスできています。このようにAdapterクラスによってPrinter/Oldprinterに変更が不要である点がAdapterデザインパターンの特徴です。
特異メソッドを使ったAdapter
ここでRubyの特異メソッドを使ってAdapterを表現した場合のコードを示します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | |
このように先ほどよりもシンプルなコードでAdapterを表現できていることがわかります。
このサンプルソースはGitHubにも置いています。
クラス変更とアダプタ適用のどちらを選択すべきか?
必要なインターフェースを変更するのは、クラスや特定のインスタンスだけを直接変更したほうがずっとシンプルなコードになります。ではどのような場面でアダプタを適用すべきでしょうか?
以下の判断材料を元に、「クラス変更」か「アダプタ適用」を選択して下さい。
* 問題のクラスの理解がある、変更が比較的少ない => クラス変更 * オブジェクトが複雑/完全な理解がない => アダプタ適用
Special Thanks
Ruby でデザインパターン2-2: Adapter(委譲)
Amazon.co.jp: Rubyによるデザインパターン: Russ Olsen, ラス・オルセン, 小林 健一, 菅野 裕, 吉野 雅人, 山岸 夢人, 小島 努: 本
変更来歴
12/10 09:00 GitHubへのサンプルソースの設置。導入文の修正
12/11 00:00 書籍へのリンクをAmazon アフィリエイトに変更
12/12 23:45 ソースコードに説明を追加
06/21 09:25 Ruby2.0.0対応、読みづらい部分を修正