具有Fluent接口的C ++ Builder模式 [英] C++ Builder pattern with Fluent interface

查看:83
本文介绍了具有Fluent接口的C ++ Builder模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用流利的接口来实现生成器模式,以在C ++中构建对象。我希望构建器遵循CRTP模式。
在Java中,我将执行以下代码。

I am trying to implement builder pattern with fluent interface for building the objects in C++. I want the builder to follow CRTP pattern. In Java, I would do something similar to the below code. How do I do the same in C++?

下面是一些具有基类和派生类的Java代码。派生类的生成器继承基类的生成器。.

The below is some java code that has a base class and a derived class. The derived class's builder inherits the base class's builder..

// 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();


推荐答案

这是使用C ++的一种方法:

Here is one way to do it in 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();
}






以下是一个示例将只允许在右值引用(由构建器返回)上更改值:


Here is an example that will only allow the values to be changed on an rvalue reference (as returned by the builder):

#include <utility>

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 std::move(static_cast<T&>(*this)); 
    }
};

class DerivedClass : public BaseClass<DerivedClass> {
    int derived_class_variable;
public:
    DerivedClass&& setDerivedClassVariable(int variable) && { 
        derived_class_variable = variable; 
        return std::move(*this); 
    }
};

int main()
{
    // Creating an instance of DerivedClass
    DerivedClass dInstance = DerivedClass::builder()
        .setBaseClassVariable(5)
        .setDerivedClassVariable(10)
        .build();

    //dInstance.setBaseClassVariable(34); // will not compile
}






这是使用 Proto 类的第三种解决方案,该类由 builder()返回。私有成员函数必须使用语句来指定,以便它们可以由 Proto 公开使用。最后, build()函数返回 DerivedClass ,它不公开成员函数。


Here is a third solution that uses a Proto class which is returned by the builder(). The private member functions have to be specified with using statements to that they can be made available for public use by Proto. Finally the build() function returns the DerivedClass which does not expose the member functions.

template<typename T>
class BaseClass;

class DerivedClass;

template <typename T>
class Proto : public T {
public:
    using BaseClass<T>::setBaseClassVariable;
    using T::setDerivedClassVariable;
};

template <typename T>
class Builder {
public:
    static Proto<T> builder() { return {}; }
    T& build() { return static_cast<T&>(*this); }
};

template <typename T>
class BaseClass : public Builder<T> {
    int base_class_variable;
    Proto<T>& setBaseClassVariable(int variable) {
        base_class_variable = variable;
        return static_cast<Proto<T>&>(*this);
    }
    friend class Proto<T>;
};

class DerivedClass : public BaseClass<DerivedClass> {
    int derived_class_variable;
    Proto<DerivedClass>& setDerivedClassVariable(int variable) {
        derived_class_variable = variable;
        return static_cast<Proto<DerivedClass>&>(*this);
    }
    friend class Proto<DerivedClass>;
};

int main()
{
    // Creating an instance of DerivedClass
    DerivedClass dInstance = DerivedClass::builder()
        .setBaseClassVariable(5)
        .setDerivedClassVariable(10)
        .build();

    //dInstance.setBaseClassVariable(34); // cannot access private member
}

这篇关于具有Fluent接口的C ++ Builder模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆