2012-11-13 18 views
8

Piszę kod obsługi komunikatów, przy czym każda wiadomość jest strukturą POD. Na sposób pisania tego byłoby zdefiniować abstrakcyjną klasę bazową, z wirtualnym functiosn dla każdego typu wiadomości npImplikacje używania mpl :: inherit_linearly do definiowania interfejsów

class AbstractHandler 
{ 
public: 
    virtual void handleMessage(const MessageType1& msg) =0; 
    virtual void handleMessage(const MessageType2& msg) =0; 
    virtual void handleMessage(const MessageType3& msg) =0; 
    virtual void handleMessage(const MessageType4& msg) =0; 
}; 

a następnie utworzyć pochodzących konkretnych klas, które implementują funkcje Handler:

class ConcreteHandler : public AbstractHandler 
{ 
public: 
    virtual void handleMessage(const MessageType1& msg); 
    virtual void handleMessage(const MessageType2& msg); 
    virtual void handleMessage(const MessageType3& msg); 
    virtual void handleMessage(const MessageType4& msg); 
}; 

Jeśli nowe wiadomości są dodawane do systemu AbstractHandler muszą być aktualizowane wraz ze wszystkimi wyprowadzonymi typami.

Ewentualnie mogę przechowywać wszystkie obsługiwane typy wiadomości w sekwencji mpl i używać mpl::inherit_linearly do generowania abstrakcyjnej klasy bazowej.

(Uwaga: Ja już używać mpl::vector typów komunikatów gdzie indziej w kodzie).

np: koparki

typedef mpl::vector< MessageType1, MessageType2, 
        MessageType3, MessageType4 > message_types; 

template< class Message > 
class Wrapper 
{ 
public: 
    virtual void handleMessage(const Message& msg) = 0; 
protected: 
    ~Wrapper(){} 
}; 

class AbstractHandler 
    : public mpl::inherit_linearly< message_types 
            , mpl::inherit< mpl_1, Wrapper<mpl::_2> > 
            >::type 
{ 
public: 
    virtual ~AbstractHandler() {} 
}; 

betonowe następnie czerpać z AbstractHandler. Oznacza to, że gdy do systemu dodawane są nowe typy wiadomości, jest to po prostu przypadek zmiany sekwencji mpl::vector<types...> message_types, dodania nowych funkcji handleMessage do klas pochodnych.

Moim zdaniem ta zmniejsza utrzymanie długoterminowego, ponieważ AbstractHandler automatycznie mieć czyste funkcje wirtualne dla wszystkich wiadomości w mpl::vector message_types

Pod względem wydajności czy są jakieś wady do korzystania z tej metody?

Jakie są konsekwencje użycia mpl::inherit_linearly do generowania abstrakcyjnych klas bazowych?

Odpowiedz

3

Zrobiłem podobny kod wcześniej (i robię to znowu dzisiaj).

Nie ma kosztów innych niż koszty wywołane spadkiem. Głównie dlatego, że ostateczny typ jest określany w czasie kompilacji, a nie w czasie wykonywania.

Jednak może to spowodować wydłużenie czasu kompilacji w stosunku do rozmiaru listy typów wiadomości. Jeśli chcesz, podobnie jak ja, napisać klasę dispatchera wiadomości (która może zająć dowolne informacje do dowolnego programu obsługi tego typu), może to być kosztowne w czasie kompilacji.

W przeciwnym razie jest dobrze.

Wystarczy zrozumieć implikację tego rodzaju konfiguracji: lista obsługiwanych wiadomości jest definiowana podczas kompilacji, a nie w czasie wykonywania. Niektóre systemy zdarzeń są uruchomieniami ze względu na wymagania dotyczące użycia. Upewnij się więc, że tego chcesz w swoich przypadkach użycia.

+0

dzięki za potwierdzenie moich przemyśleń na ten temat. Mam teraz działające rozwiązanie, które jest częścią interfejsu API używanego przez usługi klienta podczas przetwarzania komunikatów. Do tej pory wszyscy użytkownicy lubią API ... MPL z pewnością pomaga w tworzeniu solidnego kodu ... – mark

+0

Po stronie użytkownika ma jednak kilka wad: mniej oczywiste jest, jakie funkcje należy zdefiniować. Dobry (najnowszy) kompilator da wyraźny komunikat, więc myślę, że jest w porządku. Byłoby również lepiej, gdyby istniał sposób zmuszenia użytkownika do wyraźnego nadpisania funkcji (aby upewnić się, że nie popełniają błędów). – Klaim

Powiązane problemy