Implementazione di una logica "macchina di stato" per i metodi richiesti da un oggetto in C ++

0

Cosa ho: 1 oggetto / classe ipotetico + altre classi e metodi correlati che mi danno funzionalità.

Cosa voglio:

  1. collegamento di questo oggetto a metodi da 0 a N in tempo reale su richiesta quando viene attivato un evento
  2. Ogni evento è correlato a un singolo metodo o una classe, quindi un singolo evento non significa necessariamente "connetti solo questo metodo 1" ma può anche significare "connettere tutti i metodi da quella classe o un gruppo di metodi"
  3. Evitare gli elenchi collegati perché devo sfogliare l'intero elenco per sapere quali metodi sono collegati, perché ciò non garantisce che i metodi collegati siano mantenuti in un ordine particolare (diciamo un ordine alfabetico in base al loro nome o classe), e anche perché questo comporta una quantità massiccia di utilizzo dei puntatori.

Esempio:

Ho un oggetto Employee Jon , Jon acquisisce conoscenza e dimentica le cose abbastanza facilmente, quindi le sue abilità possono variare durante un periodo di tempo, sono responsabile di ciò che Jon può aggiungere o rimuovere dal suo CV, come posso implementare questa logica?

    
posta user827992 22.06.2012 - 21:27
fonte

1 risposta

1

Riguardo a 1. e 2.

Quello che stai descrivendo in realtà non mi sembra una "macchina dello stato" (E temo di non poter dare molto senso all'esempio nel contesto di ciò che hai descritto).
Una macchina a stati in genere comporta la transizione tra stati noti quando viene colpita una condizione per quello stato particolare; sembra più che stai cercando di memorizzare un elenco di abbonamenti di eventi che possono cambiare arbitrariamente nel tempo - per questo probabilmente hai bisogno di qualcosa come il pattern Observer.

Riguardo a 3.

Non ho mai riscontrato alcuna situazione in C ++ in cui una lista concatenata scritta a mano sia affatto desiderabile; dovresti preferire le librerie standard come regola generale. std :: deque o std :: map potrebbe essere un buon punto di partenza come mezzo per memorizzare sottoscrittori / osservatori.

Utilizzando un moderno compilatore C ++ 11, è possibile implementare un std::map< std::string, std::function<T>> per ciascuno degli eventi a cui si desidera sottoscrivere (con la stringa / chiave utilizzata per identificare l'obiettivo dell'osservatore per la successiva rimozione o modifica dell'abbonamento ).

std :: funzione < T > ti permette di usare qualsiasi tipo di oggetto callable, lambda, funzione o raccoglitore di funzione al curry come abbonato, la cui firma callable corrisponde a T .

ad esempio, con std::function< void() > potresti ragionevolmente usare

std::function<void()> fred = [](){ std::cout << "hello world"; };
fred();  // call the lambda

o

struct foo {
    void operator() () { std::cout << "hello world"; }
};

std::function<void()> bob = foo();
bob();  // call the functor

o

void foo() { std::cout << "hello world"; }

// ---------------------------------------

    std::function<void()> blah = foo;
    blah();   // call the function

o

class MyClass
{
public:
    void func() { std::cout << "hello world" << std::endl; }
};

// -----------------------------------------------------

    MyClass obj;
    std::function<void()> meow = std::bind( &MyClass::func, obj );

    meow();  // Call the member function using the object

Da questo, dovrebbe essere abbastanza facile immaginare un contenitore pieno di oggetti std :: function. Naturalmente, se necessario, puoi anche avvolgere la funzione std :: in un'altra classe (il che ti porterà un po 'più vicino al pattern GoF Observer).

    
risposta data 23.06.2012 - 08:56
fonte

Leggi altre domande sui tag