大佬教程收集整理的这篇文章主要介绍了c – 在使用工厂模式时,我应该以任何方式避免向下转换吗?,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在研究的协议是为慢速网络的自动控制而设计的,例如rS485,ZigBee,窄带PLC等.我们设计了主服务器的工厂模式.当接收到新帧时,我们首先识别该帧的相关设备类型,调用工厂方法以生成新的“解析器”实例,并将该帧分派给解析器实例.
我们的专有协议是用纯二进制实现的,我们可能需要的每个信息都记录在帧本身中,因此基本接口可以定义得尽可能简单.我们还为我们的工厂实现了自动注册方法(这里省略了与std :: map操作相关的详细代码):
// This is our "interface" base-class class parser { public: virtual int parse(unsigned char *) = 0; virtual ~parser() { } }; // The next two classes are used for factory pattern class instance_generator { public: virtual parser *generate() = 0; }; class parser_factory { private: static std::map<int,instance_generator*> classDB; public: static void add(int id,instance_generator &genrator); parser *get_instance(int id); }; // the two template classes are implementations of "auto-regisrtation" template <class G,int id> class real_generator : public instance_generator { public: real_generator() { parser_factory::add(ID,this); } parser *generate() { return new G; } }; template <class T,int n> class auto_reg : virtual public parser { private: static real_generator<T,N> instance; public: auto_reg() { instance; } }; template <class T,int n> parser_generator<T,N> auto_reg<T,N>::instance; // and these are real parser implementations for each device type class light_sensor : public auto_reg<light_sensor,1> { public: int parse(unsigned char *str) { /* do something here */ } }; class power_breaker : public auto_reg<power_breaker,2> { public: int parse(unsigned char *str) { /* do something here */ } }; /* other device parser */
这种工厂模式运行良好,并且很容易花费新的设备类型.
然而,最近我们试图与现有的控制系统接口,提供类似的功能.目标系统很老,它只提供基于ASCII的,类似AT命令的串行接口.我们设法解决了与PTY的通信问题,但现在要解决的问题是解析器实现.
目标系统的命令接口非常有限.我不能只是等待并听取传入的内容,我要轮询状态,我必须轮询两次 – 首先轮询头部,第二次轮询有效负载 – 以获得完整命令.这对我们的实现来说是一个问题,因为我要将两个帧传递给解析器实例,以便它可以工作:
class legacy_parser : virtual public parser { public: legacy_parser() { } int parse(unsigned char *str) { /* CAN NOT DO ANYTHING WITHOUT COMPLETE FRAMES */ } virtual int parse(unsigned char *header,unsigned char *payload) = 0; }; class legacy_IR_sensor : public legacy_parser,public auto_reg<legacy_IR_sensor,20> { public: legacy_IR_sensor(){ } int parse(unsigned char *header,unsigned char *payload) { /* Now we can finally parse the complete frame */ } };
换句话说,我们需要调用派生类的方法,并且该方法未在基类中定义.我们使用工厂模式生成派生类的实例.
现在我们有几个选择:
>简单地将两个字符串连接成一个不起作用.两个字符串都包含一些设备指定的信息,它们应单独解析.如果我们采用这种方法,我们将在解析字符串之前从解析器实例中执行一些“预解析”.我们认为这不是一个好主意.
>将parser_factory :: get_instance()的返回转发给legacy_parser.
>创建另一个独立工厂,该工厂仅包含派生自legacy_parser的类.
>更改instance_generator和parser_factory的定义,以便它们也可以生成(legacy_parser *),同时保持所有现有代码不受影响:
class instance_generator { public: virtual parser *generate() = 0; virtual legacy_parser *generate_legacy() { return NULL; } }; class extended_parser_factory : public parser_factory { public: legacy_parser *get_legacy_instance(int id); };
>使用访问者模式实现“智能指针”以处理从legacy_parser派生的实例:
class smart_ptr { public: virtual void set(parser *p) = 0; virtual void set(legacy_parser *p) = 0; }; class parser { public: parser() { } virtual int parse(unsigned char *) = 0; virtual void copy_ptr(smart_ptr &sp) // implement "Visitor" pattern { sp.set(this); } virtual ~parser() { } }; class legacy_parser : virtual public parser { public: legacy_parser() { } void copy_ptr(smart_ptr &sp) // implement "Visitor" pattern { sp.set(this); } int parse(unsigned char *str) { /* CAN NOT DO ANYTHING WITHOUT COMPLETE FRAMES */ } virtual int parse(unsigned char *header,unsigned char *payload) = 0; }; class legacy_ptr : public smart_ptr { private: parser *miss; legacy_parser *hit; public: legacy_ptr& operator=(parser *rhv) { rhv->copy_ptr(*this); return *this; } void set(parser* ptr) { miss=ptr; /* ERROR! Do some log or throw exception */ } void set(legacy_parser *ptr) { hit = ptr; } legacy_parser& operator*() { return *hit; } ~legacy_ptr() { if(miss) { delete miss; } if(hit) { delete hit; } } };
很明显,使用dynamic_cast<>进行DowncasTing对我们来说这是最简单的方法,但我们都不喜欢这个想法,因为我们都觉得向某些人倾斜是“邪恶的”.然而,没有人能够准确地解释为什么它是“邪恶的”.
在我们做出决定之前,我希望听到有关这些选项的更多评论.
以上是大佬教程为你收集整理的c – 在使用工厂模式时,我应该以任何方式避免向下转换吗?全部内容,希望文章能够帮你解决c – 在使用工厂模式时,我应该以任何方式避免向下转换吗?所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。