ずっと前から教養としてデザインパターンを勉強せなばと思っていてこの本を読みましたので、感想を残しておきます。
Javaは自分が最初に学んだ言語というのもあったし、基本的なインターフェースや抽象クラスあたりの知識があればよかったので、読み進めることができました。
4年前は「Bridgeパターン?何それ?」と思ってissueにメモったりしてたのですが、結局何も理解していませんでした...
4年越しに読んでみると、「機能クラスの階層」と「実装クラスの階層」を分けることのありがたみを理解することができました。やはりコードを書いていくうちに、拡張性などが課題となった経験を重ねて、実際に使う時のイメージが湧きやすくなったからだと思います。
GoFのデザインパターンはもちろん、自分の知らなかった新しい単語についても学ぶことができました。
ダブルディスパッチとVisitorパターン
ダブルディスパッチとは、メソッドの引数に渡されたオブジェクトに対して、自分自身を引数として別のメソッドを実行する方法。Scalaだとこんな感じ
class A { def foo(b: B): Unit = { b.bar(this) } }
Visitorパターンはこのダブルディスパッチの応用。Visitorパターンは、実際のデータ構造と、それに対する処理を分離するのが目的。この本では、ファイルとディレクトリの走査を例としていた。「実際のデータ構造」=「ファイルやディレクトリ」、「それに対する処理」=「走査」でありそれを行うのがVisitor。
まず、Visitorはデータ構造を訪問する visit
メソッドを、それぞれのオブジェクトに対して実装する。
trait Visitor { def visit(file: File): Unit def visit(directory: Directory): Unit }
そして、訪問者を受け入れるElementはインターフェースとして accept
メソッドを持つ。この accept
の中でVisitorの visit
メソッドを呼び出す。
trait Element { def accept(v: Visitor): Unit }
こうすることによってVisitor側では、(1)visit
する対象によって具体的な処理を変更することができる (2) Visitorの具体的な実装によって、それぞれ処理を変更することができる。
そしてElement側では、Elementの具体的なオブジェクトに応じて、Visitorを受け入れた時にそのVisitorをどのように伝播させていくかを変更することができる。
Scalaで実装した詳細はこちらの Github を参照してください
参考:ダブル・ディスパッチ~ 典型的なオブジェクト指向プログラミング・イディオム ~
intrinsic/extrinsic
- intrinsicな情報:共有させる情報。主に場所や状況に 依存しないもの
- extrinsicな情報:共有させない情報。主に場所や状況に依存するもの
今まで暗黙知的に実装していたパターンに名前がつくと、引き出しから取り出しやすくなるし、他の人とのコミュニケーションもスムーズにいきそうですね。
Scalaでのデザインパターンは、関数型プログラミングの影響も受けているので、以下の本を読んだりして別途勉強したいです。
追記:会社の勉強会で読むことになりました!