Цепочка манипулирования объектами - PullRequest
5 голосов
/ 11 ноября 2011

в моем приложении у меня есть три интерфейса ICapture<T>, IDecoder<T, K> и IBroadcaster<K>.

Теперь я реализую, например, класс VideoCapture, унаследованный от Capture<IntPtr> (IntPtr - это необработанные данные, созданные классом). Когда данные генерируются объектом VideoCapture, я сначала хочу декодировать их с T до K, а затем транслировать их.

То, что я хочу знать: как бы вы это связали? Просто написав такой метод, как

var data = videoCapture.GetData();
var decoded = decoder.Decode(data);
broadcaster.Broadcast(decoded);

Или есть какие-то шаблоны дизайна, которые я мог бы использовать? Я знаю схему цепочки ответственности . Я мог бы представить написание таких классов, как CaptureHandler, DecoderHandler и BroadcastHandler, наследуемых от HandlerBase. HandlerBase предоставит механизмы для передачи объектов следующему обработчику.

var handler1 = new CaptureHandler();
var handler2 = new DecodeHandler();
handler1.SetNext(handler2);
handler1.Handle(object);

Но я не знаю, является ли это лучшим подходом для моей ситуации.

Ответы [ 2 ]

3 голосов
/ 11 ноября 2011

Почему вы хотите избежать метода? Это просто, и я не вижу никаких недостатков для вашего приложения.

Если шаблон GetData => Decode => Broadcast полезен для других захватов, вы можете сделать метод универсальным.

1 голос
/ 11 ноября 2011

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

Decoder(VideoCapture<T> captureDevice)
{
}

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

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

Но если бы я рискнул предположить, я думаю, что нормальная ОО-иерархия была бы лучшим и самым простым способом.

Итак, есть базовый класс Capture, в котором есть виртуальный метод GetData (). Затем вы создадите подклассы для различных видов захвата, которые вы делаете. «CapturePal», «CaptureSecam», «CaptureMeSecam» и т. Д. Опять же, я полагаю, что для вас будет достаточно подклассификации, а не универсального параметра типа (будет ли Capture<float>() , а также Capture<StringBuilder>() иметь смысл в вашем приложении?)

Так что, когда у вас есть базовый класс и подклассы для ваших функций захвата, сделайте то же самое для ваших классов Decoder и Broadcaster. Базовый класс Decoder, подкласс "DivxDecoder", "MpegDecoder". Базовый класс Broadcaster с подклассом "TVBroadcaster", "IPBroadcaster", "TCPBroadcaster" и т. Д.

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

Это позволит вам связать их в цепочку следующим образом

var myProcessingChain = new TVBroadcaster(new DivxDecoder (new CaptureSecam(inputData))));

при условии, что все классы захвата принимают один и тот же тип ввода.

Другой вариант - использовать интерфейсы. Если в вашем приложении есть несколько классов, которые могут действовать как, например, как средство захвата и декодирования.

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

...