我一直在努力訓練double-dispatch pattern並且很難。我終於嘗試了一個示例程序來幫助我理解。 Here's的要點。但後來我決定嘗試一下without Double dispatch,解決方案看起來不像平常那麼糟糕。我究竟做錯了什麼?嘗試瞭解雙派遣模式
編輯:根據建議,我已發佈此問題here。保持此鏈接重定向。
我一直在努力訓練double-dispatch pattern並且很難。我終於嘗試了一個示例程序來幫助我理解。 Here's的要點。但後來我決定嘗試一下without Double dispatch,解決方案看起來不像平常那麼糟糕。我究竟做錯了什麼?嘗試瞭解雙派遣模式
編輯:根據建議,我已發佈此問題here。保持此鏈接重定向。
在單個調度---你在大多數現代OO語言中看到---一種方法是根據單個對象的運行時類型調度。這顯示爲點運算符(在ruby,java,javascript等)或箭頭運算符(perl,C++)。
# look, ma single dispatch!
# method on obj's run-time type that is called
dentist.work_on(patient)
雙調度,然後,將基於對象的運行時類型。這看起來有幾種方式;該方法應該活在哪個對象上?
# 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
像groovy這樣的語言有多個調度概括上面的第二個例子;他們在選擇運行哪種方法時考慮所有參數的運行時類型。有關groovy和多次調度,請參閱this blog post。
大多數現代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
雙重派遣模式就是我所說的一個低級別的模式,因爲其他的模式是建立在它。例如,訪問者模式嚴重依賴於雙重調度模式。
更新只看見自己的要旨。你的第一要義並不是真的在做雙重調度。當然,你要派遣兩次,但你並沒有改變第二次派遣的行爲。把它改成雙派遣我會做這樣的事情。
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)
處詢問這是一個很好的問題我認爲訪問者模式實際上是一種實現多次調度的常用方式。見例如http://en.wikipedia.org/wiki/Double_dispatch#Double_dispatch_in_C.2B.2B同樣你的牙醫例子可能有點混亂,因爲只有一名牙醫,所以你不需要雙重派遣。 :) – Sarien 2013-04-06 08:00:04
@Sarien好點,我已經增加了一個醫生的例子。是的,訪客是一種非常常見的雙重派遣方式。 – 2013-04-06 09:31:18
您可能對http:// http://programmers.stackexchange.com/有更好的運氣。雖然這是一個有趣的問題,但它不太適合Stack Overflow;本網站傾向於選擇具有「正確答案」的具體問題。 – 2013-04-06 01:23:39
我不同意;在SO – 2013-04-06 04:12:30