ООП: передача настроек в класс Builder - PullRequest
2 голосов
/ 16 октября 2011

В моем клиенте я хотел бы указать стратегии, которые будут использоваться в классе, создаваемом строителем.

Однако я не могу передать эти объекты стратегии строителю, поскольку их инициализация частично обрабатывается строителем.Тем не менее, мне все еще нужно сообщить конструктору, какой объект использовать и какие дополнительные параметры передать ему.

Вот класс Builder

public class MarketGeneratorBuilder {
    private MarketGenerator.Parameters parameters;

    public MarketGeneratorBuilder(MarketGenerator.Parameters parameters) {
        this.parameters = parameters;
    }

    public MarketGenerator build() {
        return new MarketGenerator(
            parameters,
            new GoodsGenerator(
                new UniformDistribution(
                    new ValueRange(0,parameters.getNumberOfLevels()-1)
                )
            ),
            new ITGenerator(),
            new OTGenerator(),
            new IOTGenerator(
                new UniformDistribution(
                    new ValueRange(1,parameters.getNumberOfLevels()-2)
                ),
                new BundlesGenerator(
                    new ForwardMarkovDistribution(
                        new MarkovDistribution.Parameters(
                            new ValueRange(0,parameters.getNumberOfLevels()-1),
                            0.1,
                            0.1
                        )
                    ),
                    new UniformDistribution(
                        new ValueRange(1,parameters.getNumberOfGoodsToCreate()-1)
                    )
                ),
                new BundlesGenerator(
                    new BackwardMarkovDistribution(
                        new MarkovDistribution.Parameters(
                            new ValueRange(0,parameters.getNumberOfLevels()-1),
                             0.2,
                             0.2
                        )
                    ),
                    new UniformDistribution(
                        new ValueRange(1,parameters.getNumberOfGoodsToCreate()-1)
                    )
                )
            )
        );
    }
}

Распределения (UniformDistribution, ForwardMarkovDistribution, ForwardMarkovDistribution и, возможно, еще больше впереди.) сейчас жестко запрограммированы, но должны быть выбраны клиентом.Диапазон значений определяется Builder (объекты ValueRange).Тем не менее, некоторые дистрибутивы принимают дополнительные параметры (ForwardMarkovDistribution принимает ValueRange, alpha, beta), которые должны быть определены клиентом.

Единственное решение, которое я вижу, - это вытащить ValueRange из конструктора в сеттер.Но это кажется неправильным, поскольку это существенное поле для объекта.Также я бы хотел, чтобы клиентский код не содержал внутренней логики компоновщика.Скорее,

DistributionType levelDistribution = new DistributionType(Distributions.UNIFORM);
DistributionType goodsDistribution = new DistributionsType(Distributions.MARKOV_FORWARD, 0.1,0.1);

Но в этом случае я не понимаю, как обеспечить целостность данных.Это означает, что когда клиент выбирает Distributions.UNIFORM, больше нет параметров для передачи.Или в случае с Distributions.MARKOV_FORWARD он должен пройти альфа и бета.

Итак, я надеялся, что вы сможете указать мне лучший образец.Спасибо!

Ответы [ 2 ]

2 голосов
/ 16 октября 2011

Для полной гибкости добавьте поставщика / фабрику для каждого из дистрибутивов:

interface DistributionProvider<D extends Distribution> {
  D create(ValueRange vr);
}

class UniformDistributionProvider implements DistributionProvider<UniformDistribution> {
  UniformDistribution create(ValueRange vr) {
    return new UniformDistribution(vr);
  }
}

class ForwardMarkovDistributionProvider implements DistributionProvider<ForwardMarkovDistribution> {

  private final MarkovDistribution.Parameters params;

  ForwardMarkovDistributionProvider(MarkovDistribution.Parameters pParams) {
    params = pParams;
  }

  ForwardMarkovDistribution create(ValueRange vr) {
    return new ForwardMarkovDistribution(vr, params);
  }
}

// etc.

(Удалите ValueRange из MarkovDistribution.Parameters.)

В основном, каждый изпровайдеры хранят все необходимые параметры для раздачи, кроме ValueRange.Затем клиенты могут создавать провайдера для распределения, которое они хотят, настраивая его с соответствующими значениями.Строитель получит эти экземпляры DistributionProvider и использует их для создания распределений, передавая ValueRange.

0 голосов
/ 16 октября 2011

Я вижу здесь несколько разных шаблонов.

  • Вы можете использовать несколько различных build методов. buildUniform() и buildMarkov(float alpha, float beta).
  • У вас может быть пара разных классов строителей: MarketGeneratorMarkovBuilder. Они могут иметь базовый класс с защищенным методом build. [Не уверен, что мне нравится этот]
  • Вы можете добавить значения alpha и beta в класс parameters и вызвать исключение, если они недоступны для MARKOV_FORWARD, и выдать исключение, если они доступны для UNIFORM.
  • Если ValueRange является постоянным для всего сборщика, то я не вижу причин, по которым, как вы упоминаете, вы не могли добавить его в parameters или поместить установщик в конструктор, чтобы добавить его.
  • Возможно, вы захотите использовать внедрение зависимостей (в моде Spring) для всех константных подклассов. У строителя могут быть сеттеры для всех, вместо того, чтобы быть жестко закодированными.

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...