開発
Visitorパターン
makuta
Visitorとは、英語で「訪問者」を意味します。受け入れる側の処理を変更することなく処理を追加できるのが、Visitorパターンです。
例えば、家の「水道工事」を行ってもらう場合、、、
「水道工事業者」を家に呼んで、「あとは、よろしくお願いします!」といって、後は、全てお任せしますよね。他にも、「電気工事業者」を呼ぶことや、「リフォーム業者」を呼ぶこともあるでしょう。これらのどの訪問者にも、「あとは、よろしく」と言って、ほとんどの作業を任せるはずです。お任せの仕方に多少違いはあるかもしれませんが、最終的には、全てを業者にお任せすることになると思います。
このように、受け入れる側の処理を変更(追加)することなく処理を追加することができるのが、Visitorパターンです。
Visitorパターンでは、データと処理を分けて、別々のクラスとして作ります。そして、この2つのクラスが、互いに相手のメソッドを呼び出すことによって、連携して動作をします。この仕組をダブルディスパッチ(2重の振り分け)といいます。
このパターンは、Iteratorパターンの解説とよく似てるいます。
- Visitorパターン:集合の要素を1つ1つ巡って、何らかの処理を行っていく時のパターン
- Iteratorパターン:集合の要素に純に1つずつアクセスするときのパターン
Iteratorパターンを使って、集合の要素に何らかの処理を行う場合は次のようなコードになります。
Iterator it = set.iterator(); while(it.hasNext()){ Data data = (Data)it.next(); operator.operate(data); }
Iteratorパターンではたくさんの要素について1つ1つ処理を行っていることがよく分かります。
一方、Visitorパターンでは、次のようなコードになります。
operator.operator(data);
Visitorパターンでは、ある1つの要素について呼び出せば、ダブルディスパッチの仕組みにより、その要素から辿れる要素について、次々と処理が行われていきます。そのため、呼び出し側から見ると、あたかもたった1つの要素について処理を行っているように見えてしまうのです。
Visitorパターンを使うべきケースは、
- 集合に、型(クラス)が異なる要素が含まれている
- 要素の型(クラス)に応じて、行う処理が異なる
- ある要素から、次の要素を辿る時に、次の要素の型(クラス)がわからない
ツリー構造に対して何らかの処理をする時は、Visitorパターンを使うことが理想だと思われているかもしれません。ですが、実際にVisitorパターンを使うべきであることは、稀なように思われます。
集合にいくつかの異なる要素が含まれている場合でも、Visitorパターンを使わない時のデメリットは、if文の分岐が並ぶことだけである。Visitorパターンを使うと、再帰呼び出しが持つシンプルさや、Iteratorによるデータ構造と処理の分離といったメリットを失うことになる。Visitorパターンを使う際には、これらのメリット・デメリットを秤にかける必要があります。