Come semplificare la struttura di un software di monitoraggio che utilizza il pattern Observer?

2

Sto lavorando a un progetto in cui devo monitorare lo stato di un ascensore. Finora, il mio design ha questo aspetto:

Stiamoutilizzandounalibreriaditerzepartiperleggereemonitorareivaloriintemporealedallogiccontrollerdell'elevatore.Untagèunvaloreinteroinunregistrodimemoriadellogiccontroller.Adesempio,DM140contieneladirezionedell'elevatore.

Usounlivelloadattatoripermantenereisolatoildominiodell'applicazionedallalibreriaditerzeparti.

Neldominio,ElevatorDirectionMonitorprendeilvaloreinteroElevatorTag,estrapolaladirezionecorrentedell'elevatoreepoinotificaaisuoiclienticheladirezionedell'elevatoreècambiata.Finqui,tuttobene.

Eccoilmioproblema:cisarannounsacco(uncentinaioopiù)ditipidiinformazionidamonitoraredall'ascensore,comeilpavimentocorrente,seleportesonoaperte/chiuse,ecc.Secontinuocosì,Dovròcreareunaclassedimonitorperognitipodiinformazionechevogliomonitorare(adesempio,ElevatorFrontDoorStatusMonitor,ElevatorRearDoorStatusMonitor)eognimonitorassociatoallapropriainterfacciaObserver.Questosignificamoltolavoro.Hocercatoditrovareunaltromodoperstrutturarelamiaapplicazione,manonhotrovatonulladipiù"elegante".

La logica di base in ogni classe di monitor sarebbe praticamente la stessa su tutta la linea: ascoltare la modifica del valore su un'istanza ElevatorTag , estrapolare le informazioni dal nuovo valore del tag e quindi notificare gli osservatori. Il problema sembra derivare dal fatto che ogni classe di osservatori deve avere una firma di interfaccia diversa (ad esempio ElevatorDirectionObserver ha NotifyDirectionChanged(ElevatorDirection newDirection) quando DoorStatusMonitor avrebbe piuttosto qualcosa di simile a NotifyDoorStatusChanged(DoorPosition frontOrRear, DoorStatus openOrClosed) ).

Pensi che la soluzione su cui sto lavorando sia accettabile. In caso contrario, qualcuno potrebbe suggerire quali schemi dovrei usare o investigare, o qualcosa che potrebbe aiutarmi a semplificare il mio design?

    
posta Michaël Blanchet 31.08.2015 - 14:59
fonte

3 risposte

-2

È un buon istinto da ostacolare nella creazione di cento classi molto simili. Questo è generalmente un segno che dovrebbero essere istanze . Potresti provare qualcosa come:

monitors.createIntMonitor("Floor", "DM141")
monitors.createBoolMonitor("Front door open", "DM142")
monitors.createEnumMonitor("Direction", "DM140", ["Up", "Down", "None"])
// or alternately
monitors.createEnumMonitor<ElevatorDirection>("Direction", "DM140")

monitors.getMonitor("Front door open").addObserver(observer)

Questo design può essere facilmente inizializzato dinamicamente, ad esempio da un file di configurazione o database, inclusa l'aggiunta di nuovi campi, senza richiedere la ricompilazione dell'app. Questi tipi di cambiamenti spesso finiscono per essere il più grande costo di manutenzione se lo fai staticamente. Richiede anche molte meno modifiche di copia / incolla / minori, che sono una grande fonte di errori.

Lo svantaggio è che non ricevi più errori di compilazione quando metti un RearDoorMonitor in una variabile che si aspetta un FrontDoorMonitor . È anche un po 'più problematico raggruppare più osservatori in una classe, ma in genere non è comunque la soluzione migliore.

I tuoi abbonati per un monitor enum templato potrebbero avere questo aspetto:

// Common interface
template <typename T>
class Subscriber
{
    public:
      virtual void receiveEvent(T t) = 0;
};

// Individual subscriber instance
class ElevatorSubscriber : public Subscriber<ElevatorDirection>
{
    public:
        void receiveEvent (ElevatorDirection direction);
};
    
risposta data 31.08.2015 - 18:24
fonte
0

Stai cercando Boost.Signals2. In questo caso, ogni "monitor" è solo un'istanza di boost::signals2::signal<void(ElevatorDirection)> , ad esempio. E ogni "osservatore" è solo una funzione casuale della firma appropriata, come una lambda. Puoi semplicemente chiamare il segnale ogni volta che ti serve e aggiungere / rimuovere i metodi forniti. Nessuna cazzata richiesta.

Il modello di Osservatore non è affatto un modello. È solo una classe. Una classe che non devi nemmeno implementare.

    
risposta data 04.09.2015 - 19:41
fonte
-1

Vorrei provare a trovare una via di mezzo. Se ci sono, come hai scritto, un centinaio di tipi di informazioni, la possibilità è alta ci saranno molti tipi simili, con firme di interfaccia simili. Ad esempio, invece di avere ElevatorFrontDoorStatusMonitor e ElevatorRearDoorStatusMonitor , crea ElevatorDoorStatusMonitor , dove "Front" o "Rear" è solo un parametro. Se sono presenti sensori per ogni piano, impostare il numero del piano come parametro.

Potresti finire con una dozzina di diversi tipi di osservatori, forse più, forse meno, ognuno dei quali supporta una diversa lista di "tag pic". Quali dei tag pic che puoi raggruppare dipende, ovviamente, da quanto differiscono le operazioni nel tuo programma per i diversi tipi.

    
risposta data 31.08.2015 - 18:22
fonte

Leggi altre domande sui tag