带继承的Builder模式链式调用问题:寻求更优解决方案
链式Builder模式的类型匹配问题
我们有一个抽象构建类AbstractBufferBuilder,包含构建Buffer的通用方法:
class AbstractBufferBuilder { public: AbstractBufferBuilder &setBufferData(...) { // 具体实现 return *this; } };
还有一个继承自它的具体构建类ConcreteBufferBuilder:
class ConcreteBufferBuilder : public AbstractBufferBuilder { public: ConcreteBufferBuilder &addAttribute(...) { // 具体实现 return *this; } Buffer* build(){ return new Buffer(...); } };
当尝试通过链式调用创建Buffer对象时:
ConcreteBufferBuilder().setBufferData(...).addAttribute(...).build();
这段代码无法编译——因为setBufferData()返回的是AbstractBufferBuilder类型引用,而该基类并没有addAttribute()方法。
已尝试的解决方案
1. CRTP模板基类方案
通过奇异递归模板模式(CRTP)让基类方法返回派生类的引用:
template<class Builder> class AbstractBufferBuilder { public: Builder &setBufferData(...) { // 具体实现 return *dynamic_cast<Builder*>(this); } }; class ConcreteBufferBuilder : public AbstractBufferBuilder<ConcreteBufferBuilder> { public: ConcreteBufferBuilder &addAttribute(...) { // 具体实现 return *this; } Buffer* build(){ return new Buffer(...); } };
该方案可以正常实现链式调用,但模板会增加编译和链接的开销,导致编译时间变长、生成的可执行文件体积增大。
2. 派生类包装函数方案
将基类的通用方法改为保护的实现函数,在派生类中编写同名的公开包装函数,返回派生类自身的引用:
class AbstractBufferBuilder { protected: void setBufferDataImpl(...) { // 具体实现 } }; class ConcreteBufferBuilder : public AbstractBufferBuilder { public: ConcreteBufferBuilder &setBufferData(...){ AbstractBufferBuilder::setBufferDataImpl(...); return *this; } ConcreteBufferBuilder &addAttribute(...) { // 具体实现 return *this; } Buffer* build(){ return new Buffer(...); } };
这种方式需要为每个新的Builder派生类重复编写包装代码,复用性差,维护成本高。
我希望保留链式调用的写法,请问有没有更优的解决方案?
内容的提问来源于stack exchange,提问作者AlexusXX
相关产品推荐
相关产品推荐

