update.普段よく使うJavaライブラリにも、GoFのデザインパターンが隠されています。日々の作業が忙しく見逃しがちですが、たまにはじっくり一種の芸術ともいえる美しい設計を味わってみましょう。rt.jar(Javaのコアライブラリなので最初からある)Javaのロガー(SLF4J)を生成するシーンです。ソースコードはそのままで、クラスパスに追加するjarファイルを取り替えるだけで、ロガーの実装を自由に選ぶことができます。インターフェイスと実装をとてもきれいに切り離していることに芸術性を感じます。鑑賞のポイントJavaのロギングライブラリはいろいろある2ため、プロジェクトごとに異なったものを利用していることも多いかと思います。他のプロジェクトのソースを自分のプロジェクトでも使おうとしたとき、利用されているロガーが異なると、ソースコードを修正しないといけなかったり、ロガーの設定ファイルを二重で管理しないといけなかったりと、美しくないことになってしまいます。今回の鑑賞ポイントは、アダプタークラスを用意することで、実装クラス(ロガー)をすり替えても同じ使い方ができるようになっているところです。おまけに、実装クラスのすり替えはjarを置き換えるだけという、古典的ですが最もシンプルな方法が採用されています。設計の美しさはもとより、ライブラリを使う私たちに対しての設計者の粋な図らいに畏敬の念を抱きます。以下で一緒に鑑賞していきましょう。冒頭のコードをAdapterパターンを使わないで書くと、以下のようになります。Logger.getLogger(this.getClass());ロガーごとにインスタンス取得時の記述と、import文の記述が異なっています。インスタンス化するLoggerクラスが異なるため、それぞれで使えるメソッドも異なります。この状態でロギングライブラリを変更すると、たくさんのソースコードを置換することになってしまいます。特定のロギングライブラリにしか存在しないメソッドを使っていた場合は、置換さえできません。冒頭のコードではAdapterパターンが使われています。クラスパスに追加するjarファイルです。どのロギングライブラリにも3つのjarファイルがありますが、役割は同じで、SLF4Jのインターフェイス(SLF4Jが配布しているjarファイル)SLF4Jのインターフェイスの実装。内部でそれぞれのロギングライブラリを呼ぶ。それぞれのロギングライブラリの実装となっています。ロギングライブラリの種類とjarの役割を表にすると以下のようになります。rt.jar※IFはインターフェイスの略そして、ロガーインスタンスは、どのロギングライブラリを使っていても、一律で次のように生成します。LoggerFactory.getLogger(this.getClass());...このgetLoggerメソッドの中身は以下のようになっています。...}ILoggerFactory、およびLoggerの実装クラスは以下のようになっています。いずれのクラスもそれぞれのロギングライブラリのIF実装(アダプター)jarに含まれます。org.slf4j.jul.JDK14LoggerAdapterこのソースコードを追っていくと、次のような流れでLoggerFactoryとLoggerのインスタンスが生成されることがわかります。各クラスがどのjarに含まれているかを【】で書いています。それを意識すると理解しやすいです。最終的に生成されたLoggerは、ロギングライブラリの実装jarに含まれるクラスではなく、IF実装のjarに含まれるクラスであることがポイントです。このクラスは、ロギングライブラリの参照をメンバ変数に保持していて、ログ出力のときにはそれを呼び出します。以上のようにすることで、SLF4Jを使う人は、ロギングライブラリのインスタンスを直接参照するのではなく、そのアダプターに相当するIF実装クラスを参照して使用することになります。ch.qos.logback.core.XXXAppender【ロギングライブラリ実装のjar】AdapterパターンのまとめAdapterパターンは、Wrapper(ラッパー)パターンと呼ばれることもあります。そのままでは使いにくいクラスを使いやすいように適合させるために、新しいクラスでラップするのです。ちなみに、そのままでは使いにくいクラスというのは、似たようなクラス間でメソッドに統一感がなかったり、ソースコードが汚かったりするクラスのことです。どうりでSLF4Jのインターフェイスはきれいなはずです。それは、きれいにすることを目的に、Adapterパターンで整形された結果なのです。今回の例にはAdapterパターンの魅力が最大限引き出されているものを選びましたが、ここまで徹底的にやらなくても(IF、IF実装、ロギングライブラリ実装でjarファイルを分けるまでやらなくても)、既存のままでは使いにくいクラスのラッパークラスを作るだけで、Adapterパターンを使っていることになります。Adapterパターンへの専門家のコメント多くの専門家からも、Adapterパターンを評価するコメントが寄せられています。結城浩さんプログラムの世界でも、すでに提供されているものがそのままつかえないときに、必要な形に変換してから利用することがよくあります。「すでに提供されているもの」と「必要なもの」の間の「ずれ」を埋めるようなデザインパターン、これがAdapterパターンです。lang_and_engineさんAdapterパターンをうまく使えば,開発チーム内の対人関係が良くなる,という効用もある。低スキル者が滅茶苦茶なコードを書いた際,そのクラスのソースコード自体に横から手を出して他のメンバが書き変えようとすると,最初にコーディングした方のプログラマは「傷ついた」と感じるものだ。それを避けるために,ラッパークラスを一段かませて,ラッパークラス側を充実させて高品質にする。最後にわざわざ美術館に行かなくても、たった1行のコードを眺めるだけで知的な愉しみを味わうことができるのは、プログラマーの醍醐味でしょう。実際の開発シーンでは、jarファイルの追加には、Mavenなどのモジュール管理ツールを使います。Mavenの設定ファイル(pom.xml)への記述方法は、こちらのSLF4Jの公式リファレンスを参照してください。Sato@takuya-s沖縄在住のリモートエンジニア。アプリケーションの設計が好き。言語はRuby/PHP/Python/JavaScript/Java/C/C++/Objective-C。DB/Apache/Nginx。upLoginユーザーは見つかりませんでした。