2011-11-11 17 views
5

nella mia applicazione Ho tre interfacce ICapture<T>, IDecoder<T, K> e IBroadcaster<K>.Concatenamento manipolazione oggetti

Ora implemento ad esempio una classe VideoCapture che eredita da Capture<IntPtr> (IntPtr è i dati grezzi prodotti dalla classe). Quando i dati vengono generati da un oggetto di VideoCapture, in primo luogo voglio decodificarlo da T a K e quindi trasmetterlo.

Quello che voglio sapere è: come lo metteresti in catena? Semplicemente scrivendo un metodo come

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

O ci sono schemi di progettazione, che potrei usare? Conosco il modello di responsabilità. Potrei immaginare di scrivere classi come CaptureHandler, DecoderHandler e BroadcastHandler ereditando da HandlerBase. HandlerBase fornirebbe i meccanismi per consegnare gli oggetti al gestore successivo.

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

Ma non so se questo è l'approccio migliore per la mia situazione.

+3

Cosa speri di scrivere che potrebbe essere più chiaro o più utile della tua prima versione? Quello sembra morto semplice per me. – mquander

+0

se Capture , Decoder e Broadcaster sono tutte interfacce, dovresti probabilmente rinominarle per prefigurarle con un 'I'. Questa è una convenzione di denominazione .NET standard che renderà il tuo codice più facile da comprendere e leggere –

+1

Non sovrappensarlo, solo [mantieni semplice] (http://en.wikipedia.org/wiki/KISS_principle) ... Il tuo il primo snippet di codice va bene –

risposta

1

È possibile un'istanza di ciascun oggetto nel costruttore del successivo. Se, per esempio, ogni istanza decoder ha bisogno di un'istanza di acquisizione video a lavorare, allora si può avere un costruttore come segue ...

Decoder(VideoCapture<T> captureDevice) 
{ 
} 

E fare la stessa cosa per l'emittente, ovvero avere un costruttore che si terrà a un'istanza del decodificatore come parametro.

In effetti, non sono nemmeno sicuro che avresti bisogno di farmaci generici. Si potrebbe fare, a seconda dell'applicazione. Dopo tutto, possiamo solo vedere una piccola parte in questa domanda. Non sei sicuro di quali tipi passerai in ciascuna di queste classi e in che modo il parametro Type verrà utilizzato al loro interno.

Ma se dovessi azzardare un'ipotesi, penso che la normale gerarchia OO sarebbe la soluzione migliore e più semplice.

Quindi, avere una classe base Capture, che ha il metodo virtuale GetData(). Creerai quindi sottoclassi per i diversi tipi di Cattura che fai. "CapturePal", "CaptureSecam", "CaptureMeSecam", ecc Anche in questo caso, io sono indovinare che sub classificare sarebbe abbastanza per voi, piuttosto che un parametro di tipo generico (sarebbe Capture<float>() così come Capture<StringBuilder>() essere significativo nella vostra applicazione?)

Quindi, una volta che hai una classe base e sottoclassi per la tua funzionalità di cattura, fai lo stesso per le tue classi Decoder e Broadcaster. Base class Decoder, sottoclasse "DivxDecoder", "MpegDecoder". Emittente di classe base con sottoclasse "TVBroadcaster", "IPBroadcaster", "TCPBroadcaster" ecc.

Ora, i costruttori per ciascuna classe base prenderanno l'altra classe base come parametro e chiamano i metodi appropriati.

Ciò permetterà di concatenano loro come segue

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

assumendo che tutte le classi di cattura assumono lo stesso tipo di ingresso.

L'altra opzione è utilizzare le interfacce. Se la tua applicazione ha alcune classi che possono agire sia come catturatore che come decodificatore, ad esempio.

Pensa un po 'di più se hai davvero bisogno di Generics. I generici sono utili quando si desidera riutilizzare gli algoritmi e si vuole essere agnostici al tipo, mentre si applica la sicurezza del tipo. Essere agnostici di tipo è diverso dall'essere in grado di accettare un insieme di tipi che condividono una comunanza. In questo caso è possibile ottenere la comunanza tra i tipi utilizzando l'ereditarietà.

+0

ben messo per quanto riguarda i generici rispetto alle gerarchie OO –

+0

Il problema principale con l'accoppiamento delle classi in questo modo è che limita la loro flessibilità. Cosa succede se vuoi trasmettere un flusso che è già stato decodificato, magari salvato su disco? –

+0

Non proprio. Le classi base ti danno ancora la stessa flessibilità delle interfacce. Si potrebbe facilmente implementare una sottoclasse che eredita da "Decoder" e invece di eseguire la decodifica in memoria, la legge dal disco. La classe di trasmissione otterrebbe solo una classe base di decodificatore e chiamerà "GetData" su di essa. Anche i generici non ti daranno più flessibilità. O dovrai accettare qualsiasi tipo, come float, StringBuilder, limitando così ciò che puoi fare nel metodo o devi avere i vincoli di tipo. Quindi torniamo alle classi base o alle interfacce. Il CIO potrebbe aiutare, ma rimane la stessa storia di OO. – Chaitanya

3

Perché si desidera evitare il metodo? È semplice e non vedo svantaggi per la tua applicazione.

Se il modello =>Decode =>Broadcast è utile per altre acquisizioni, è possibile rendere generico il metodo.

+1

Se vuoi mettere un'etichetta su di esso come un motivo di progettazione, puoi chiamarlo modello KIS :) –