LoginSignup
0
1

More than 5 years have passed since last update.

【デザインパターン】 Visitorパターン

Last updated at Posted at 2015-06-21

概要

構造と振る舞いを分離するためのパターン

以下の5種類のクラスからなる
1. Visitorクラス(3.に対するVisitオペレーションを宣言する)
2. ConcreteVisitorクラス(1.で宣言されたVisitオペレーションを実装する)
3. Elementクラス(要素の抽象クラス、visitorを受け取るAcceptオペレーションを宣言する)
4. ConcreteElementクラス(要素の具象クラス、3.で宣言されたAcceptオペレーションを実装する)
5. ObjectStructureクラス(要素を列挙し、それらに対するオペレーションをvisitorに任せるためのインターフェイスを提供する)

具体例と実装

訪問販売を例にすると

上記1~5はそれぞれ
1. 訪問販売クラス(DoorToDoorSalesmanクラス、訪問のインターフェイスを定義)
2. 生命保険販売クラス、健康食品販売クラス(LifeInsuranceDoorToDoorSalesmanクラス、HealthyFoodDoorToDoorSalesmanクラス。訪問販売で各家庭を訪れる)
3. 世帯クラス(Householdクラス、訪問販売員を受け入れるインターフェイスを定義)
4. 単身世帯クラス、家族世帯クラス(SingleHouseholdクラス、FamilyHouseholdクラス各訪問販売員を受け入れる)
5. 販売員派遣元クラス

が対応する。
コードの詳細は以下

door_to_door_salesman.rb
class DoorToDoorSalesman
  def visit(household)
  end
end
life_insurance_door_to_door_salesman.rb
class LifeInsuranceDoorToDoorSalesman < DoorToDoorSalesman
  def visit(household)
    household.greet
    # 家を訪問
  end
end
healthy_food_door_to_door_salesman.rb
class HealthyFoodDoorToDoorSalesman < DoorToDoorSalesman
  def visit(household)
    household.greet
    # 家を訪問
  end
end
household.rb
class Household
  def accept(door_to_door_salesman)
  end
end
single_household.rb
class SingleHousehold < HouseHold
  def initialize
  end

  def accept(door_to_door_salesman)
    door_to_door_salesman.visit(self)
  end

  def greet
    puts 'こんにちは'
  end
end
family_household.rb
class FamilyHousehold < HouseHold
  def initialize
  end

  def accept(door_to_door_salesman)
    door_to_door_salesman.visit(self)
  end

  def greet
    puts 'こんにちは、誰に御用でしょうか??'
  end
end
door_to_door_salesman_agency.rb
class DoorToDoorSalesmanAgency
  attr_accessor :household_list

  def initialize
    # 訪問先顧客情報
    @household_list = Array.new
  end

  def add(household)
    @household_list << household
  end

  def remove(household)
    @household_list.delete(household)
  end
end
client.rb
agency = DoorToDoorSalesmanAgency.new
agency.add(SingleHouseHold.new)
agency.add(FamilyHouseHold.new)

life_insurance_salesman = LifeInsuranceDoorToDoorSalesman.new
healthy_food_salesman = HealthyFoodDoorToDoorSalesman.new

agency.household_list.each do |household|
  household.accept(life_insurance_salesman)   
  household.accept(healthy_food_salesman)
end

メリット

  • 構造とオペレーションが分離されていることによりOCPなコードになり、要素への新しいオペレーションの追加が容易
  • オペレーションを実行する要素の型がわからなくとも共通のクラスからオペレーションを呼び出せる

まとめ

オペレーションを加えるオブジェクトのクラスに変更を加えずに新しいオペレーションを定義することが出来るパターン

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1