जब एक MessageFactory वर्ग को लागू करने के लिए संदेश वस्तुओं मैं की तरह कुछ इस्तेमाल किया instatiate के संकलन समय पर एक AbstractFactory में निर्माता तरीकों रजिस्टर एक नया XXX_MSG जोड़ने और स्विच स्टेटमेंट को संशोधित करने के लिए।गतिशील रूप से सी ++ का उपयोग कर टेम्पलेट्स
कुछ शोध के बाद मुझे संकलन समय पर संदेशफैक्टरी को गतिशील रूप से अपडेट करने का एक तरीका मिला, इसलिए मैं संदेश संदेशों को संशोधित करने के बिना जितना चाहूं उतने संदेश जोड़ सकता हूं।
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
class Message
{
protected:
inline Message() {};
public:
inline virtual ~Message() { }
inline int getMessageType() const { return m_type; }
virtual void say() = 0;
protected:
uint16_t m_type;
};
template<int TYPE, typename IMPL>
class MessageTmpl: public Message
{
enum { _MESSAGE_ID = TYPE };
public:
static Message* Create() { return new IMPL(); }
static const uint16_t MESSAGE_ID; // for registration
protected:
MessageTmpl() { m_type = MESSAGE_ID; } //use parameter to instanciate template
};
typedef Message* (*t_pfFactory)();
class MessageFactory⋅
{
public:
static uint16_t Register(uint16_t msgid, t_pfFactory factoryMethod)
{
printf("Registering constructor for msg id %d\n", msgid);
m_List[msgid] = factoryMethod;
return msgid;
}
static Message *Create(uint16_t msgid)
{
return m_List[msgid]();
}
static t_pfFactory m_List[65536];
};
template <int TYPE, typename IMPL>
const uint16_t MessageTmpl<TYPE, IMPL >::MESSAGE_ID = MessageFactory::Register(
MessageTmpl<TYPE, IMPL >::_MESSAGE_ID, &MessageTmpl<TYPE, IMPL >::Create);
class PingMessage: public MessageTmpl < 10, PingMessage >
{⋅
public:
PingMessage() {}
virtual void say() { printf("Ping\n"); }
};
class PongMessage: public MessageTmpl < 11, PongMessage >
{⋅
public:
PongMessage() {}
virtual void say() { printf("Pong\n"); }
};
t_pfFactory MessageFactory::m_List[65536];
int main(int argc, char **argv)
{
Message *msg1;
Message *msg2;
msg1 = MessageFactory::Create(10);
msg1->say();
msg2 = MessageFactory::Create(11);
msg2->say();
delete msg1;
delete msg2;
return 0;
}
यहाँ टेम्पलेट करता MessageFactory वर्ग में पंजीकरण से जादू, सभी नए संदेश कक्षाएं: यह क्लीनर और आसान कोड बनाए रखने के लिए के लिए के रूप में मैं जोड़ने के लिए तीन अलग-अलग स्थानों को संशोधित करने की जरूरत नहीं है/संदेश वर्गों को हटाने की अनुमति देता है (उदाहरण के लिए पिंगमेसेज और पोंगमेसेज) जो संदेश टीएमपीएल से उप-वर्ग है।
यह महान काम करता है और कोड रखरखाव सरल करता है लेकिन मैं अभी भी इस तकनीक के बारे में कुछ सवाल हैं:
यह एक ज्ञात तकनीक/पैटर्न है? क्या नाम है? मैं इसके बारे में अधिक जानकारी खोजना चाहता हूं।
मैं नए कंस्ट्रक्टर्स MessageFactory :: m_List [65536] एक std :: नक्शा भंडारण लेकिन करने के लिए सरणी बनाना चाहते तो कारण बनता कार्यक्रम भी मुख्य तक पहुँचने से पहले SEGFAULT लिए()। 65536 तत्वों की एक सरणी बनाना ओवरकिल है लेकिन मुझे पर कोई डायनामिक कंटेनर नहीं मिला है।
संदेश संदेश के उप-वर्ग वाले सभी संदेश वर्गों के लिए मुझे निर्माता को कार्यान्वित करना होगा। यदि नहीं, तो यह संदेश फैक्टरी में पंजीकृत नहीं होगा।
उदाहरण के लिएPongMessage के निर्माता टिप्पणी:
class PongMessage: public MessageTmpl < 11, PongMessage > { public: //PongMessage() {} /* HERE */ virtual void say() { printf("Pong\n"); } };
PongMessage वर्ग नहीं MessageFactory द्वारा पंजीकृत किया जा रहा में परिणाम होगा और कार्यक्रम MessageFactory :: बनाएं (11) लाइन में SEGFAULT हैं । प्रश्न
कक्षा क्यों पंजीकृत नहीं होगी? मुझे 100+ संदेशों के खाली कार्यान्वयन को जोड़ने के लिए मुझे अक्षम और अनावश्यक लगता है।
# 1 CRTP (की तरह) http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern है – Anycorn
# 3 क्योंकि MessageTmpl के निर्माता सुरक्षित है (हो सकता है) – Anycorn
वैसे, अपने कोड सूची की जाँच करें। यह भटक गया है; तथा । वर्ण। मैंने इसे संकलित किया, हालांकि मुझे इसे सेगमेंटेशन गलती मिल रही है। क्लास टेम्पलेट स्थिर सदस्य प्रारंभिकरण के वास्तव में कूल उपयोग के लिए – Anycorn