当实现MessageFactory类来实例化Message对象时,我使用了类似的东西:
class MessageFactory
{
public:
static Message *create(int type)
{
switch(type) {
case PING_MSG:
return new PingMessage();
case PONG_MSG:
return new PongMessage();
....
}
}
这工作正常但每次添加新消息时我都要添加一个新的XXX_MSG并修改switch语句。
经过一些研究后,我发现了一种在编译时动态更新MessageFactory的方法,因此我可以根据需要添加任意数量的消息,而无需修改MessageFactory本身。这样可以更简洁,更容易维护代码,因为我不需要修改三个不同的位置来添加/删除消息类:
#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类中注册从MessageTmpl继承的所有新Message类(例如PingMessage和PongMessage)来实现神奇。
这很好用并简化了代码维护,但我仍然对这个技术有一些疑问:
这是一种已知的技术/模式吗?是什么名字?我想搜索更多信息 关于它。
我想创建用于存储新构造函数的数组 的MessageFactory :: m_List [65536] 一个std :: map但这样做会导致程序在到达main()之前发生段错误。 创建一个包含65536个元素的数组是有点过分,但我还没有找到方法 使这个动态容器。
对于作为MessageTmpl子类的所有消息类,我必须实现 构造函数。如果不是,它将不会在MessageFactory中注册。
例如,注释PongMessage的构造函数:
class PongMessage: public MessageTmpl < 11, PongMessage > { public: //PongMessage() {} /* HERE */ virtual void say() { printf("Pong\n"); } };会导致PongMessage类没有被MessageFactory和 程序会在 的MessageFactory ::创建(11) 线。问题是
为什么班级不会注册?必须添加100+的空实现 我需要的信息效率低下且不必要。