Let's assume, that we have AbstractBufferBuilder
class that contains some common methods for building some Buffer
classes:
class AbstractBufferBuilder {
public:
AbstractBufferBuilder &setBufferData(...) {
//some code
return *this;
}
};
And we have ConcreteBufferBuilder
class:
class ConcreteBufferBuilder : public AbstractBuilder {
public:
ConcreteBufferBuilder &addAttribute(...) {
//some code
return *this;
}
Buffer* build(){
return new Buffer(...);
}
};
To create new Buffer class, we can do
ConcreteBufferBuilder().setBufferData(...).addAttribute(...).build();
But this code won't be compiled because setBufferData()
returns AbstractBufferBuilder
that doesn't contain addAttribute()
.
I've tried to use templates to solve this problem:
template<class Builder>
class AbstractBufferBuilder {
public:
Builder &setBufferData(...) {
//some code
return *dynamic_cast<Builder*>(this);
}
};
class ConcreteBufferBuilder : public AbstractBuilder<ConcreteBufferBuilder> {
public:
ConcreteBufferBuilder &addAttribute(...) {
//some code
return *this;
}
Buffer* build(){
return new Buffer(...);
}
};
It works, but templates give extra work to the compiler and linker, so it increases build time and file size.
Another possible solution is to use a wrapper for AbstractBufferBuilder
methods:
class AbstractBufferBuilder {
protected:
void setBufferDataImpl(...) {
//some code
}
};
class ConcreteBufferBuilder : public AbstractBuilder {
public:
ConcreteBufferBuilder &setBufferData(...){
AbstractBuilder::setBufferDataImpl(...);
return *this;
}
ConcreteBufferBuilder &addAttribute(...) {
//some code
return *this;
}
Buffer* build(){
return new Buffer(...);
}
};
But then we need to write same code every time we create a new Builder class which is also not good.
Of course, we can abandon the use of chain calls, but I want to solve this particular problem.
Same question already asked: Builder Pattern and Inheritance, but my question is little bit different.
Is there any better solution to this problem?