尝试理解双重调度模式

udi*_*dit 10 ruby design-patterns

我一直试图弄清楚双重调度模式并且很难过.我终于尝试了一个示例程序来帮助自己理解.这是要点.但后来我决定尝试没有Double发送,并且解决方案看起来不像往常那么可怕.我究竟做错了什么?

编辑:根据建议,我在这里发布了这个问题.保持此链接的重定向.

Mic*_*uff 18

在单一调度中 - 您在大多数现代OO语言中看到的 - 根据单个对象的运行时类型调度方法.这显示为点运算符(在ruby,java,javascript等中)或箭头运算符(perl,c ++).

# look, ma single dispatch!
# method on obj's run-time type that is called
dentist.work_on(patient)
Run Code Online (Sandbox Code Playgroud)

那么,双重调度将基于两个对象的运行时类型.这看起来有几种方式; 该方法应该以哪个对象为生?

# Hmm, this looks weird.
# Is the method in to dentist.class or patient.class?
(dentist, patient).do_dentistry()


# okay, this looks more familiar; the method lives on obj1.class
# This only works in static-typed languages which support double dispatch
# in which you declare the type of the method parameters.
dentist.work_on(patient)

class Dentist
   def work_on(Adult patient); ...; end
   def work_on(Child patient); ...; end
end
Run Code Online (Sandbox Code Playgroud)

具有多个调度的groovy等语言概括了上面的第二个例子; 在选择要运行的方法时,它们会考虑所有参数的运行时类型.例如,请参阅关于groovy和多次发送的博客文章.

大多数现代OO语言只有单一调度,而多调度模式试图获得多次调度到语言中的好处.它甚至适用于像ruby这样的动态语言.它的工作原理是连续两次执行单次调度.第一个方法调用将调用第二个对象上的方法.

class Dentist
    def work_on(patient)
       patient.dispatch_work(self)
    end
    def work_on_adult(patient)
      drill_as_hard_as_you_can(patient)
    end
    def work_on_child(patient)
      use_bubble_gum_toothpaste(patient)
      give_toothbrush_to(patient)
    end
end

class Doctor
    def work_on(patient)
       patient.dispatch_work(self)
    end
    def work_on_adult(patient)
      do_checkup(patient)
    end
    def work_on_child(patient)
      assure_presence_of(patient.guardian)
      ask_questions_to(patient.guardian)
      do_checkup(patient)
      give_cheap_toy_to(patient)
    end
end



class Adult
    def dispatch_work(dentist)
      dentist.work_on_adult(self)
    end
end

class Child
    def dispatch_work(dentist)
      dentist.work_on_child(self)
    end
end
Run Code Online (Sandbox Code Playgroud)

双调度模式就是我所说的低级模式,因为其上构建了其他模式.例如,访问者模式在很大程度上依赖于双重调度模式.


更新刚看到你的要点.你的第一个要点并不是真正做双重调度.当然,您要派遣两次,但是您没有改变第二次调度中的行为.要将其更改为双重发送,我会做这样的事情.

class Chicken
  def make_dispatch dish
    dish.make_with_chicken self
  end
end

class Beef
  def make_dispatch dish
    dish.make_with_beef self
  end
end


module Dish
  def make meat
    meat.make_dispatch self
  end
end

class Sandwich
  include Dish

  def make_with_chicken chicken
    puts "Grilled Chicken Sandwich"
  end

  def make_with_beef beef
    puts "Roast Beef Sandwich"
  end
end

class Stew
  include Dish

  def make_with_chicken chicken
    puts "Thai curry"
  end

  def make_with_beef beef
    puts "Beef stew"
  end
end

class Casserole
  include Dish

  def make_with_chicken chicken
    puts "Chicken Pot Pie--or something"
  end

  def make_with_beef beef
    puts "Shepard's Pie"
  end
end

Sandwich.new.make(Chicken.new)
Stew.new.make(Chicken.new)
Casserole.new.make(Beef.new)
Run Code Online (Sandbox Code Playgroud)