C++;具有Fluent界面的Builder模式 我尝试用Fluent接口实现Builder模式,用于构建C++中的对象。我希望生成器遵循CRTP模式。 在Java中,我将执行类似于以下代码的操作。如何在C++中实现同样的操作?< /P>
下面是一些具有基类和派生类的java代码。派生类的生成器继承基类的生成器C++;具有Fluent界面的Builder模式 我尝试用Fluent接口实现Builder模式,用于构建C++中的对象。我希望生成器遵循CRTP模式。 在Java中,我将执行类似于以下代码的操作。如何在C++中实现同样的操作?< /P>,c++,c++11,c++builder,builder,fluent,C++,C++11,C++builder,Builder,Fluent,下面是一些具有基类和派生类的java代码。派生类的生成器继承基类的生成器 // Base class public abstract class BaseClass { private final int base_class_variable; BaseClass(final Builder <?> builder) { this.base_class_variable = builder.base_class_variable; }
// Base class
public abstract class BaseClass {
private final int base_class_variable;
BaseClass(final Builder <?> builder) {
this.base_class_variable = builder.base_class_variable;
}
public abstract static class Builder <B extends Builder> {
int base_class_variable;
public B setBaseClassVariable(final int variable) {
this.base_class_variable = variable;
return self();
}
protected abstract B self();
}
}
// Derived class
public final class DerivedClass extends BaseClass {
private final int derived_class_variable;
private DerivedClass(final Builder builder) {
super(builder);
this.derived_class_variable = derived_class_variable;
}
public static Builder builder() {
return new Builder();
}
public static final class Builder extends BaseClass.Builder <Builder> {
private int derived_class_variable;
public Builder setDerivedClassVariable(final int variable) {
this.derived_class_variable = variable;
return self();
}
public DerivedClass build() {
return new DerivedClass(this);
}
@Override
protected Builder self() {
return this;
}
}
}
// Creating an instance of DerivedClass
DerivedClass dInstance = DerivedClass.builder()
.setBaseClassVariable(5)
.setDerivedClassVariable(10)
.build();
//基类
公共抽象类基类{
私有final int base_class_变量;
基类(最终生成器){
this.base\u class\u变量=builder.base\u class\u变量;
}
公共抽象静态类生成器{
int base_class_变量;
公共B setBaseClassVariable(最终整数变量){
this.base_class_variable=变量;
返回自我();
}
受保护抽象B self();
}
}
//派生类
公共最终类DerivedClass扩展基类{
私有final int派生的类变量;
私有派生类(最终构建器){
超级建筑商;
this.derived_class_variable=派生_class_variable;
}
公共静态生成器(){
返回新的生成器();
}
公共静态最终类生成器扩展了BaseClass.Builder{
私有int派生的类变量;
公共生成器setDerivedClassVariable(最终整数变量){
this.derived_class_variable=变量;
返回自我();
}
公共派生类构建(){
返回新的DerivedClass(此);
}
@凌驾
受保护的生成器self(){
归还这个;
}
}
}
//创建DerivedClass的实例
DerivedClass dInstance=DerivedClass.builder()
.setBaseClassVariable(5)
.setDerivedClassVariable(10)
.build();
这里有一种用C++实现的方法:
template <typename T>
class Builder {
public:
static T builder() { return {}; }
T & build() {return static_cast<T&>(*this); }
};
template <typename T>
class BaseClass : public Builder<T> {
int base_class_variable;
public:
T& setBaseClassVariable(int variable) {
base_class_variable = variable;
return static_cast<T&>(*this);
}
};
class DerivedClass : public BaseClass<DerivedClass> {
int derived_class_variable;
public:
DerivedClass& setDerivedClassVariable(int variable) {
derived_class_variable = variable;
return *this;
}
};
int main()
{
// Creating an instance of DerivedClass
DerivedClass dInstance = DerivedClass::builder()
.setBaseClassVariable(5)
.setDerivedClassVariable(10)
.build();
}
这种方法可能会激发出更好的东西,所以我认为应该与大家分享 首先,使用构建器模式为要提供的成员创建一个类,让我们将其称为members类和immutable类来构建构建器类 members类将用于: 生成器类将从中继承 生成器类在其构造函数中接受它,以便为常量成员提供所有常量值 现在我们要创建一个fluent接口,用于设置members类上的成员变量 出现一个冲突:要使生成器类成员为常量,members类还需要使它们为常量 但是流畅的构造需要一种每次给出一个参数的方法,理想情况下,需要一种控制给出参数的顺序的方法 例如: 我们有一个表示正在运行的进程的类,要构造它,我们需要知道: 1.(命令)执行什么命令 2.(模式)是否只需要从标准输出读取(读取模式)或以交互方式使用,以要求能够写入其标准输入(写入模式) 3.(目标)stdout应重定向到哪里?是锉刀还是烟斗 为简单起见,所有参数都将由字符串表示 在每个提供的参数之后限制有效方法对于自动完成来说是很好的,但是它需要我们用有效方法定义一个范围 以及它将过渡到什么范围-对于施工的每个阶段 也许依赖类型的名称空间会更好,但如果可能的话,我想重用members类 每个参数接口由一个类表示,该类具有用于提供构造函数参数的方法。 该方法将返回一个对象,该对象的类型为下一个接口,用于提供下一个构造函数参数或完成的生成器对象 我在所有构建阶段都重用相同的对象,但是通过静态转换接口会发生变化 我们首先创建客户端将在构建器类之前使用的最后一个接口,在本例中是(3)目标参数。 让我们在此之后命名:
struct Target : protected members_class
{
builder_class havingTarget( const string& _target )
{
this->target = target;
return builder_class ( *(this) ) ;
}
};
builder类可以通过给它一个members\u类对象来构造,我们从members\u类继承,因此我们可以通过提供this指针来返回构造的builder类
在目标接口之前,我们有用于设置模式参数的接口:
struct Mode : protected Target
{
Target& inMode( const string& mode )
{
this->mode = mode;
return static_cast<Target&>(*this);
}
};
首先,让我们启用一种提供模板参数的方法,该参数将决定成员是否为常量:
template <typename T>
using noop = T;
template< template <typename> class constner = noop >
struct members_dyn_const
现在,我们从const members类中定义builder类,但接受可变成员类来构造const:
class base_process : protected members
{
public:
base_process( members_mutable _members ) : members( _members ) {}
现在,我们可以使用以下内容构造一个生成器类:
process_builder.withCommand( "ls" ).inMode( "read" ).havingTarget( "cout" );
并使用const成员创建一个不可变类
我没有在其他地方看到过这种方法的描述,所以我想分享它,因为它可能会为更好的方法提供灵感,但我不能真正推荐它,我也没有真正测试或完善过概念验证之外的代码
#include <string>
#include <iostream>
using namespace std;
namespace process
{
namespace details
{
template <typename T>
using noop = T;
template< template <typename> class constner = noop >
struct members_dyn_const
{
friend class members_dyn_const< noop >;
template< template <typename> class C>
members_dyn_const( members_dyn_const<C> m) : target(m.target), mode(m.mode), command(m.command){}
members_dyn_const () : target(""), mode(""), command(""){}
protected:
constner<const string> target;
constner<const string> mode;
constner<const string> command;
};
using members = members_dyn_const<>;
using members_mutable = members_dyn_const<std::remove_const_t>;
namespace builder
{
class base_process : protected members
{
public:
base_process( members_mutable _members ) : members( _members ) {}
void test() { /*command = "X";*/ cout << "Executing command: " << command << " in mode " << mode << " having target " << target << endl; }
};
namespace arguments
{
struct Target : protected members_mutable
{
base_process havingTarget( const string& _target )
{
this->target = target;
return base_process( *(this) ) ;
}
};
struct Mode : protected Target
{
auto& inMode( const string& mode )
{
this->mode = mode;
return static_cast<Target&>(*this);
}
};
struct Command : protected Mode
{
Mode& withCommand( const string& command )
{
this->command = command;
return static_cast<Mode&>(*this);
}
};
}
}
}
using details::builder::base_process;
using details::builder::arguments::Command;
Command process_builder = Command();
}
using namespace process;
int main()
try
{
process_builder.withCommand( "ls" ).inMode( "read" ).havingTarget( "cout" ).test();
return 0;
}
catch( exception& e )
{
cout << "ERROR:" << e.what() << endl;
return -1;
}
#包括
#包括
使用名称空间std;
名称空间进程
{
命名空间详细信息
{
模板
使用noop=T;
模板
结构成员\u动态\u常量
{
好友类成员的动态常数;
模板<模板类C>
members_dyn_const(members_dyn_const m):target(m.target)、mode(m.mode)、command(m.command){}
members\u dyn\u const():目标(“”),模式(“”),命令(“”{}
受保护的:
康斯特纳靶;
康斯特纳模式;
康斯特纳指挥部;
};
使用成员=members\u dyn\u const;
使用members_mutable=members_dyn_const;
命名空间生成器
{
类基类进程:受保护的成员
{
公众:
基进程(成员可变成员):成员(_成员){}
void test(){/*command=“X”*/cout谢谢Wally!!这能确保我
template <typename T>
using noop = T;
template< template <typename> class constner = noop >
struct members_dyn_const
constner<const string> target;
constner<const string> mode;
constner<const string> command;
using members = members_dyn_const<>;
using members_mutable = members_dyn_const<std::remove_const_t>;
template< template <typename> class C>
members_dyn_const( members_dyn_const<C> m) : target(m.target), mode(m.mode), command(m.command){}
members_dyn_const () : target(""), mode(""), command(""){}
class base_process : protected members
{
public:
base_process( members_mutable _members ) : members( _members ) {}
process_builder.withCommand( "ls" ).inMode( "read" ).havingTarget( "cout" );
#include <string>
#include <iostream>
using namespace std;
namespace process
{
namespace details
{
template <typename T>
using noop = T;
template< template <typename> class constner = noop >
struct members_dyn_const
{
friend class members_dyn_const< noop >;
template< template <typename> class C>
members_dyn_const( members_dyn_const<C> m) : target(m.target), mode(m.mode), command(m.command){}
members_dyn_const () : target(""), mode(""), command(""){}
protected:
constner<const string> target;
constner<const string> mode;
constner<const string> command;
};
using members = members_dyn_const<>;
using members_mutable = members_dyn_const<std::remove_const_t>;
namespace builder
{
class base_process : protected members
{
public:
base_process( members_mutable _members ) : members( _members ) {}
void test() { /*command = "X";*/ cout << "Executing command: " << command << " in mode " << mode << " having target " << target << endl; }
};
namespace arguments
{
struct Target : protected members_mutable
{
base_process havingTarget( const string& _target )
{
this->target = target;
return base_process( *(this) ) ;
}
};
struct Mode : protected Target
{
auto& inMode( const string& mode )
{
this->mode = mode;
return static_cast<Target&>(*this);
}
};
struct Command : protected Mode
{
Mode& withCommand( const string& command )
{
this->command = command;
return static_cast<Mode&>(*this);
}
};
}
}
}
using details::builder::base_process;
using details::builder::arguments::Command;
Command process_builder = Command();
}
using namespace process;
int main()
try
{
process_builder.withCommand( "ls" ).inMode( "read" ).havingTarget( "cout" ).test();
return 0;
}
catch( exception& e )
{
cout << "ERROR:" << e.what() << endl;
return -1;
}