Eyes, JAPAN Blog > Visitorパターン

Visitorパターン

makuta

この記事は1年以上前に書かれたもので、内容が古い可能性がありますのでご注意ください。

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パターンを使う際には、これらのメリット・デメリットを秤にかける必要があります。

Comments are closed.