Шаблон проектирования C ++ для передачи большого количества параметров - PullRequest
17 голосов
/ 05 апреля 2011

У меня есть класс разумного размера, который реализует несколько логически связанных алгоритмов (из теории графов).В качестве входных данных для алгоритма требуется около 10-15 параметров.Они не модифицируются алгоритмом, но используются для управления его работой.Сначала я объясню два варианта реализации этого.Мой вопрос заключается в том, что является обычным способом сделать это (является ли это одним из двух вариантов или нет).

Мне лично не нравится передавать эти значения в качестве параметров функции, когда N большой, особенно когда я все еще разрабатываю алгоритм.

void runAlgorithm(int param1, double param2, ..., bool paramN);

Вместо этого у меня есть класс Algorithm, который содержит алгоритмы, и у меня есть структура AlgorithmGlobals, которая содержит эти параметры.Я либо передаю эту структуру:

void runAlgorithm(AlgorithmGlobals const & globals);

, либо добавляю в класс общедоступный экземпляр AlgorithmGlobals:

class Algorithm {
public:
    AlgorithmGlobals globals;
    void runAlgorithm();
}

Тогда в другом месте я бы использовал его так:

int main() {
    Algorithm algorithm;
    algorithm.globals.param1 = 5;
    algorithm.globals.param2 = 7.3;
    ...
    algorithm.globals.paramN = 5;

    algorithm.runAlgorithm();

    return 0;
}

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

AlgorithmGlobals не делаются закрытыми, посколькуони могут быть свободно изменены до вызова функции runAlgorithm().Нет необходимости «защищать» их.

Ответы [ 6 ]

12 голосов
/ 05 апреля 2011

Это называется "Объектом параметра" , и это, как правило, хорошо.Мне не нравится версия участника, особенно называя ее «XGlobals» и подразумевая, что она распространена повсюду.Вместо этого шаблон объекта параметров обычно включает создание экземпляра объекта параметров и передачу его в качестве параметра для вызова функции.

8 голосов
/ 05 апреля 2011

Другие упоминали Параметр объекта , но есть и другая возможность: использовать Builder .

Builder позволяет опускать параметры, значения которых по умолчанию подходят, тем самым упрощая ваш код. Это особенно удобно, если вы собираетесь использовать свой алгоритм с несколькими различными наборами параметров. OTOH также позволяет повторно использовать аналогичные наборы параметров (хотя существует риск случайного повторного использования). Это (вместе с цепочкой методов) позволит вам написать код, такой как

Algorithm.Builder builder;

Algorithm a1 = builder.withParam1(1).withParam3(18).withParam8(999).build();
...
Algorithm a2 = builder.withParam2(7).withParam5(298).withParam7(6).build();
6 голосов
/ 05 апреля 2011

У вас есть несколько разных идей, которые вы должны предложить в своем дизайне:

  1. Параметры являются чисто входными данными.
  2. Параметры зависят от вашего алгоритма.
  3. Параметры имеют нормальные значения по умолчанию.

class Algorithm {
  public:
    class Parameters { // Nested class, these are specific to your algorithm.
      public:
        Parameters() : values(sensible_default) { }
        type_t values; // This is all about the data.
    };

    Algorithm(const Parameters &params) : params_(params) { }

    void run();

  private:
    const Parameters params_; // Paramaeters don't change while algorithm
};                            // is running. 

Это то, что я бы предложил.

4 голосов
/ 05 апреля 2011

Идиома именованного параметра может быть полезна здесь.

a.runAlgorithm() = Parameters().directed(true).weight(17).frequency(123.45);
4 голосов
/ 05 апреля 2011

Я использую эту технику, которую вы уже упоминали:

void runAlgorithm(AlgorithmGlobals const & globals);

Но назовем класс AlgorithmParams.

1 голос
/ 05 апреля 2011

предложение Почему бы вам не сделать это вместо этого:

class Algorithm {
public:
Algorithm::Algorithm(AlgorithmGlobals const & globals) : globals_(globals) {}

    void runAlgorithm(); // use globals_ inside this function

   private:
    const AlgorithmGlobals globals_;
    };

Теперь вы можете использовать его так:

AlgorithmGlobals myglobals;
myglobals.somevar = 12;

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