开发者

How do I simultaneously dispatch a method to a number of instances when before it only dispatched to one?

开发者 https://www.devze.com 2023-03-08 07:53 出处:网络
In my hypothetical application, users can ask questions, which are then answered by an Oracle. You can use the Predictor.predictor method to get an appropriate Oracle, to whom you can then direct your

In my hypothetical application, users can ask questions, which are then answered by an Oracle. You can use the Predictor.predictor method to get an appropriate Oracle, to whom you can then direct your questions. When you #ask a question, you'll get a response, along with the Oracle's certainty (a floating-point 开发者_如何转开发number in the range 0..1) about its response.

class BaseOracle; def ask(question); ...; end; end
class UnreliableOracle < BaseOracle; ...; end

module Predictor
  def self.predictor
    @predictor ||= UnreliableOracle.new
  end
end

Predictor.predictor.ask("How many fingers am I holding up?")
 # => ["three fingers", 0.2]

In this implementation, you get the same Oracle every time, an UnreliableOracle instance. What I would like to do is to change the implementation of Predictor.predictor so that methods which are invoked on it are delegated to a collection of Oracles, some of which are better than others. In other words, I want it to work something like this:

class BaseOracle; ...; end
class UnreliableOracle < BaseOracle; ...; end
class PopCultureOracle < BaseOracle; ...; end
class ScienceOracle < BaseOracle; ...; end
class LiteraryOracle < BaseOracle; ...; end
class FingerCountingOracle < BaseOracle; ...; end

module Predictor
  def self.predictor
    ############## What goes here?
  end
end

# This actually asks several oracles for an answer and picks the best one.
Predictor.predictor.ask("How many fingers am I holding up?")
 # => ["four fingers", 1.0]

What's the best way to do that?


This is essentially the strategy design pattern, where each Oracle is effectively a strategy for answering questions.

The easiest (and perhaps cleanest) approach is to construct a MetaOracle that asks the other oracles what the right answer is and picks the best answer:

class MetaOracle
  def oracles
    @oracles ||= [ScienceOracle.new, LiteraryOracle.new, # ...
  end

  def ask(question)
    oracles.map { |o| o.ask question }.        # Ask each Oracle a question ...
      sort_by { |answer| -answer.certainty }.  # sort by the best answers ...
      first                                    # ... and pick the best one.
  end
end

module Predictor
  def self.predictor
    @predictor ||= MetaOracle.new
  end
end

Now the Oracle with the best answer wins and will be the answer that you see.

0

精彩评论

暂无评论...
验证码 换一张
取 消