C++ 使用Builder/Fluent模式最小化所需的头文件量
我正在尝试用Builder/Fluent风格创建对象,试图扩展课程中提出的一些想法。在我的测试实现中,我立即不喜欢的一个元素是客户端需要包含大量额外的头文件,以便流程正常工作,特别是当我希望通过pImpl习惯用法使用公共/私有头文件来提供库接口时。我不完全确定问题是在于我的实现,还是我只是错过了实现我想要的东西的明显的“最后一步”。C++ 使用Builder/Fluent模式最小化所需的头文件量,c++,design-patterns,pimpl-idiom,C++,Design Patterns,Pimpl Idiom,我正在尝试用Builder/Fluent风格创建对象,试图扩展课程中提出的一些想法。在我的测试实现中,我立即不喜欢的一个元素是客户端需要包含大量额外的头文件,以便流程正常工作,特别是当我希望通过pImpl习惯用法使用公共/私有头文件来提供库接口时。我不完全确定问题是在于我的实现,还是我只是错过了实现我想要的东西的明显的“最后一步”。 一般要点如下(使用飞行员玩具示例): 首先,客户端代码本身: (注意:为简洁起见,省略了各种样板文件和不相关的代码) 这里发生的是: 在Pilot.h中,
一般要点如下(使用飞行员玩具示例):
首先,客户端代码本身:
(注意:为简洁起见,省略了各种样板文件和不相关的代码) 这里发生的是:
- 在Pilot.h中,使用名为
的静态成员方法定义create()
类,该方法返回在PilotBuilder.h中定义并在Pilot.h中声明的Pilot
类的实例PilotBuilder
- 本质上,
类是一个方便的构建器,它只用于呈现Pilot的两个不同方面的构建器(PilotBuilder
和.works()
),允许您从一个构建器切换到另一个构建器.lifes()
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;
};
#include "PilotBuilder.h"
PilotBuilder Pilot::create() {
return PilotBuilder();
}
// Other definitions etc
Pilot.cpp:
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;
};
#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
类使用PilotBuilder
类提供的引用以流畅的方式实现与特定方面相关的方法,例如(.atAirline()
),它们的实现与我的查询无关为了避免向私人成员提供参考这一稍有争议的问题,我的困境是,要利用我目前的模式,客户必须如下所示:
#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
的私有成员移动到唯一的\u ptr pImpl
中,并且仍然保持静态create()
方法因为以下情况显然是不允许的: