шаблон проектирования для инициализации алгоритмов, каждый из которых принимает разные параметры - PullRequest
1 голос
/ 19 июля 2011

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

Моя цель состоит в том, чтобы все конкретные алгоритмы реализовали интерфейс, который будет примерно состоять из Init() и Run(In,Out), чтобы я мог выполнить их следующим образом:

void Process()
{
    // IAlgotrithm* algX = new CAlgX(); X:{A,B,C}
    IAlgorithm* algs[] = { algA, algB, algC }; 
    for (int i=0; i < 3; i++) {
        algs[i]->Init(...);
        algs[i]->Run(In,Out);     
    }
 }

Проблема в том, что в настоящее время каждый алгоритм принимает различную структуру в качестве входного параметра.
Например, CAlgA имеет метод Init(CAlgAParameter param), где CAlgAParameter - это структура с полями, специфичными для AlgA.Каждый алгоритм имеет свою собственную структуру, которая состоит из совершенно разных полей разных типов.Каков наилучший способ приблизиться к этому?

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

Как лучше всего подойти к этому?
Спасибо

Ответы [ 2 ]

5 голосов
/ 19 июля 2011

Почему бы не инициализировать во время построения, а просто вызвать Run() в цикле?Следовательно, при создании вы можете взять на себя ответственность пользователя за предоставление правильной конфигурации для данного алгоритма, например

IAlgorithm* algs[] = { new CAlgA(CAlgAParameter(...)), new CAlgB(CAlgBParameter(...)), new CAlgC(CAlgCParameter(...)) }; 

//loop

Использование исключений для обработки некорректной конфигурации алгоритмов.

0 голосов
/ 19 июля 2011

Для статических параметров, которые не будут изменены никаким алгоритмом, подойдет инициализация на основе конструктора.Параметры управления, которые должны быть предоставлены для каждого прогона алгоритма, могут быть определены интерфейсом (или абстрактными классами со всеми абстрактными методами) для каждого алгоритма.

public class IAlg1ControlParams {
public: 
    virtual ~IAlg1ControlParams () {}
    virtual int getParam1() = 0;
    virtual void setParam2(char val) = 0;
}

Это будет поддерживать размер вашего алгоритма таким же маленьким, каквозможно для каждого звонка.Эти интерфейсы также будут полезны для тестирования ваших алгоритмов, поскольку вам нужно только обеспечить реализацию двух интерфейсов в ваших тестах, а не какую-то большую карту параметров со строковыми ключами.Вы могли бы сделать еще лучше, используя Mocking Framework, например Google Mock .

public void WhenInputIs10_Algorithm1SetsParam2Tob() {
    Alg1 alg1 = new Alg1("Test data", 10);
    IAlg1ControlParams context = new MockAlg1ControlParams(10);
    alg1.Run(context);
    assert(context.getParam2() == 'b');
}

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

public class AlgSet1Context: public IAlg1Context, public IAlg2Context...

В рамках каждого алгоритма вам необходимо будет проверить соответствие значений в параметрах управления.Я бы порекомендовал использовать здесь шаблон шаблонного метода, чтобы у вас было базовое бизнес-правило, которое обеспечивает не виртуальную реализацию Run(ControlParams) и вызывает два защищенных виртуальных метода Verify(ControlParams) и Execute(ControlParams).Это гарантирует, что все разработчики, которые реализуют новые алгоритмы позднее, знают, что они должны проверить параметры управления.

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