我正在尝试使用Builder / Fluent风格创建对象,试图扩展课程中提出的一些想法。我立即对我的测试实现不喜欢的一个要素是客户端需要包含的大量额外头文件才能使进程工作,特别是当我希望通过pImpl惯用法使用公共/私有头时提供库接口的目的。我不完全确定问题是由于我的实施还是我错过了一个明显的最后一步'实现我想要的。
一般要点如下(使用飞行员的玩具示例):
首先是客户代码本身:
(注意:为简洁起见,省略了各种样板和无关代码)
Pilot p = Pilot::create()
.works().atAirline("Sun Air").withRank("Captain")
.lives().atAddress("123 Street").inCity("London")
这里发生的事情是:
Pilot
类使用名为create()
的静态成员方法定义,该方法返回<1}中定义的PilotBuilder
类的实例strong> PilotBuilder.h 并在 Pilot.h PilotBuilder
类是一个便利构建器,仅用于显示Pilot(.works()
和.lives()
)的两个不同方面的构建器,让您从一个构建器切换到另一个构建器Pilot.h:
class PilotBuilder;
class Pilot {
private:
// Professional
string airline_name_, rank_;
// Personal
string street_address_, city_;
Pilot(){}
public:
Pilot(Pilot&& other) noexcept;
static PilotBuilder create();
friend class PilotBuilder;
friend class PilotProfessionalBuilder;
friend class PilotPersonalBuilder;
};
Pilot.cpp:
#include "PilotBuilder.h"
PilotBuilder Pilot::create() {
return PilotBuilder();
}
// Other definitions etc
PilotBuilder.h
#include "public/includes/path/Pilot.h"
class PilotProfessionalBuilder;
class PilotPersonalBuilder;
class PilotBuilder {
private:
Pilot p;
protected:
Pilot& pilot_;
explicit PilotBuilder(Pilot& pilot) : pilot_{pilot} {};
public:
PilotBuilder() : pilot_{p} {}
operator Pilot() {
return std::move(pilot_);
}
PilotProfessionalBuilder works();
PilotPersonalBuilder lives();
};
PilotBuilder.cpp
#include "PilotBuilder.h"
#include "PilotProfessionalBuilder.h"
#include "PilotPersonalBuilder.h"
PilotPersonalBuilder PilotBuilder::lives() {
return PilotPersonalBuilder{pilot_};
}
PilotProfessionalBuilder PilotBuilder::works() {
return PilotProfessionalBuilder{pilot_};
}
您可以想象PilotProfessionalBuilder
类和PilotPersonalBuilder
类只使用{提供的引用 - 以流畅的方式实现与该特定方面相关的方法,例如(.atAirline()
) {1}}类,它们的实现与我的查询无关。
避免提供私人会员参考的轻微争议问题,我的困境是,为了充分利用我的模式,客户必须看起来像这样:
PilotBuilder
我无法弄清楚的是:
#include "public/includes/path/Pilot.h"
#include "private/includes/path/PilotBuilder.h"
#include "private/includes/path/PilotProfessionalBuilder.h"
#include "private/includes/path/PilotPersonalBuilder.h"
int main() {
Pilot p = Pilot::create()
.works().atAirline("Sun Air").withRank("Captain")
.lives().atAddress("123 Street").inCity("London");
}
,想象一下,我将链接到#include "public/includes/path/Pilot.h"
库,其余的实现居住并仍然保持相同的行为?Pilots
的私人成员移动到Pilot
并仍然保持静态{{1 }} 方法? - 因为显然不允许以下内容:
unique_ptr<Impl> pImpl
最后,我绝不是这方面的专家,所以如果我的任何术语不正确或编码实践真的需要修复,我会很乐意接受人们必须给出的任何建议。谢谢!