#ruby #design-patterns
#ruby #шаблоны проектирования
Вопрос:
В моем гипотетическом приложении пользователи могут задавать вопросы, на которые затем отвечает Oracle
. Вы можете использовать Predictor.predictor
метод, чтобы получить соответствующего Oracle
человека, которому вы затем можете направить свои вопросы. Когда вы #ask
задаете вопрос, вы получите ответ вместе с Oracle
уверенностью (число с плавающей запятой в диапазоне 0 .. 1) в его ответе.
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]
В этой реализации вы каждый раз получаете один и тот же Oracle, ненадежный экземпляр Oracle. Что я хотел бы сделать, так это изменить реализацию Predictor.predictor так, чтобы методы, которые вызываются на нем, делегировались коллекции оракулов, некоторые из которых лучше других. Другими словами, я хочу, чтобы он работал примерно так:
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]
Каков наилучший способ сделать это?
Ответ №1:
По сути, это шаблон разработки стратегии, где каждый Oracle фактически является стратегией для ответов на вопросы.
Самый простой (и, возможно, самый чистый) подход заключается в создании MetaOracle
, который запрашивает у других оракулов правильный ответ и выбирает наилучший ответ:
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
Теперь Oracle с лучшим ответом выигрывает и будет тем ответом, который вы видите.