デザインパターン-Visitor

Visitorパターンとは

Visitorパターンとは、訪問者(Visitor)オブジェクトがデータ構造要素の各オブジェクトを訪問し、その訪問先の公開されている資源を利用して処理を実行するパターンです。

Visitorパターンは「データ構造」クラスと「処理」クラスを分離することを目的とします。

データ構造と処理を分離することで、データ構造を表すクラスを変更することなく、新しい処理を容易に追加することができます。


「Visitor」とは「訪問者」を意味します。


ダブルディスパッチについて

ダブルディスパッチとは「2重の呼び出し」という意味です。

Visitorパターンでは、データと処理を別々のクラスとして作成し、2つのクラスが互いに相手側メソッドを呼び出すことで連係して動作します。

Acceptorのaccept()メソッドを呼び出し、Visitorのvisit()メソッドを呼び出すという2つのメソッド呼び出しを経て、初めて行うべき処理が決定されます。

この仕組みをダブルディスパッチといいます。


構成要素

  • Visitor(訪問者)
    • visitメソッドのインタフェースを定義します。
  • ConcreteVisitor(具体的訪問者)
    • 具体的なデータ構造の要素毎に訪問して行う処理(visitメソッド)を実装します。
  • Acceptor(受入者=データ構造)
    • 受入口のインタフェースを定義します。
  • ConcreteAcceptor(具体的受入者=具体的データ構造)
    • acceptメソッドを実装します。
  • Client(利用者)

rubyによるVisitorパターンの実装

Rubyではメソッドの引数に型を指定できないため、ダブルディスパッチャが使用できません。

メソッド名を分けて実装します。


#!/usr/bin/env ruby

# visitメソッドのインタフェースを定義します。 
class Visitor
  def visit(acceptor); end
end

# 具体的なデータ構造の要素毎に訪問して行う処理 
class ConcreteVisitor < Visitor
  def visit_a(acceptor)
    puts("[visit]" + acceptor.get_string)
  end

  def visit_b(acceptor)
    puts("[visit]" + acceptor.get_string)
  end
end

# 受入者のインタフェース
class Acceptor
  def accept(visitor); end
end

# 受入者(データ構造)
class ConcreteAcceptorA < Acceptor
  def initialize(string)
    @string = string
  end

  def accept(visitor)
    visitor.visit_a(self)
  end

  def get_string
    return(@string)
  end
end

# 受入者(データ構造)
class ConcreteAcceptorB < Acceptor
  def initialize(string)
    @string = string
  end

  def accept(visitor)
    visitor.visit_b(self)
  end

  def get_string
    return(@string)
  end
end

visitor  = ConcreteVisitor.new
acceptor_a = ConcreteAcceptorA.new("acceptor A")
acceptor_a.accept(visitor)

acceptor_b = ConcreteAcceptorB.new("acceptor B")
acceptor_b.accept(visitor)



関連ページ