Шаблон стратегии - несколько типов возврата / значений - PullRequest
2 голосов
/ 14 ноября 2009

Мы работаем над проектом обработки изображений с использованием C # и EmguCV. Наша команда состоит из 3 человек. Чтобы ускорить прогресс, мы втроем работаем над разными подзадачами или экспериментируем с разными алгоритмами одновременно.

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

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

Однако я понимаю, что при таком подходе могут возникнуть некоторые проблемы:

  1. Различные алгоритмы принимают разные входные данные (исходное изображение, некоторый другой набор параметров и т. Д.)
  2. Различные алгоритмы возвращают разные выходные данные (новое изображение, набор функций, матрица и т. Д.)

Первая проблема, которую я считаю, я могу преодолеть, сделав что-то вроде этого

Class Strategy1 : IStrategy
{
    int _code;

    // Different *input* paramteres for the strategy may be passed in the 
    // constructor depending on the type of strategy
    public Strategy1(int c)
    {
        _code = c;
    }

    // This is the method defined in the IStrategy interface
    public void execute()
    {
        // Some code that uses _code and does some processing goes here
    }
}

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

Когда я думаю о том, как решить проблему возврата нескольких типов / значений, первое, о чем я могу подумать, - это изменить тип возвращаемого значения execute с void на что-то вроде хеш-таблицы, где могут храниться различные возвращаемые параметры. и возвращенные ИЛИ имеют других членов класса, например "int _returnCode", которые могут быть получены другим методом или через свойства этого класса, доступные только для чтения.

Я не уверен, насколько хорошим было бы это решение с точки зрения принципов проектирования, и был бы рад услышать ваше мнение по этому поводу. Спасибо

Ответы [ 3 ]

4 голосов
/ 14 ноября 2009

Если единственное, что объединяет алгоритмы, это то, что они выполняются, вам следует подумать о шаблоне команды , а не о шаблоне стратегии. (По крайней мере, это лучше всего соответствует описанному вами решению.)

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

Например, это позволит вам написать код, подобный этому:

// ... logic to obtain an image and handle application flow ...

// I'm using 'image' here as a stand-in for a single object all your commands
// could derive their inputs from, or a container of all the inputs. If no such
// object exists, just do what you have to construct the commands.
ICommand[] commands = ImageCommandFactory.CreateCommands(image);

foreach(ICommand command in commands) {
    command.Execute();
}

// ... Handle commands ...

Как вы упомянули, объекты команд будут использовать открытые члены для предоставления результатов своего выполнения - в простейшей форме будет использоваться свойство, подобное public object Results { get; }. (Конечно, чем больше вы можете сузить это возвращаемое значение до стандартного ICommandResults типа, тем лучше вам будет.)

Как вы обрабатываете результаты, зависит от вас. Вы можете использовать фабрику (снова) для создания обработчика, подходящего для команды, которую вы передаете ему:

// Picks the correct type of processor, depending on the command
IResultHandler handler = ResultHandlerFactory.CreateHandler(command, form);

// renders the results to the form provided to the factory method
handler.RenderResults();

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

0 голосов
/ 14 ноября 2009

Если у вас есть свобода использования C # 4, вы можете положиться на функцию ковариант возвращаемого типа. Таким образом, вы можете определить интерфейс для выполнения как:

public object execute()

, а затем переопределить его в производных классах с типами возвращаемых данных, специфичными для этого конкретного класса.

0 голосов
/ 14 ноября 2009

Здесь есть несколько вещей:

  • наличие всего в одном файле - анти-шаблон "Большой шарик грязи"
  • Вы можете разбить его на несколько файлов, используя частичные классы, это решит вашу проблему многих людей, работающих над одним файлом, но только немного лучше.
  • Вместо шаблона стратегии, почему бы просто не создать вспомогательные классы (шаблон помощника), можно протестировать каждого помощника.
...