【问题标题】:Implement a generalized builder pattern in c++在 C++ 中实现一个通用的构建器模式
【发布时间】:2018-12-09 14:28:33
【问题描述】:

我决定使用builder 模式来避免长的未命名参数构造函数,但我有一个特定的用例。我有一个基类和一些从中继承的类,它们都必须能够单独构建。下面显示一个伪代码解释我的特殊用例:

class B
{
  int i;
  int j;
public:
  B& setI(int i) {this->i=i; return *this;}
  B& setJ(int j) {this->j=j; return *this;}
}

class I : public B
{
  int i2;
  int j2;
public:
  I& setI2(int i) {this->i2=i; return *this;}
  I& setJ2(int j) {this->j2=j; return *this;}
}
B b = B().setI(12).setJ(13); // ok
I i = I().setI(12).setJ(13).setI2(14).setJ2(15); // error the first and second function return B not I

上面的代码无法编译,因为B中的函数没有返回类I的类型。this post已经提出了解决方案,但是有限,不能单独创建基类。 我使用的是 c++11,但可以使用其他版本的 c++。

更新:

有一个解决方案是接受 B 作为 I 的构造函数的参数,但在实际问题中存在一些继承层,使用此解决方案不太实用。

【问题讨论】:

    标签: c++ c++11 design-patterns


    【解决方案1】:

    我们可以有一个Builder 用于类I,它最终分配了类I 及其基类B 的属性。 Builder 应该是 I 类的朋友,以便我们可以访问 Builder 的受保护成员,并且我们确保所有属性都可用于 Builder

    考虑类B

    class B {
    protected:
      int first;
      int second;
    
    public:
      int get_first() { return this->first; }
    
      int get_second() { return this->second; }
    };
    

    还有,班级I

    class I : public B {
      int third;
      int fourth;
    
    public:
      int get_third() { return this->third; }
    
      int get_fourth() { return this->fourth; }
    
      class Builder : public B {
        int third;
        int fourth;
    
      public:
        Builder &set_first(const int &first) {
          this->first = first;
          return *this;
        }
    
        Builder &set_second(const int &second) {
          this->second = second;
          return *this;
        }
    
        Builder &set_third(const int &third) {
          this->third = third;
          return *this;
        }
    
        Builder &set_fourth(const int &fourth) {
          this->fourth = fourth;
          return *this;
        }
    
        friend class I;
      };
    
      I(const Builder &builder);
    };
    

    因此,它允许我们为属性赋值:

    I::I(const I::Builder &builder) {
      this->first = builder.first;
      this->second = builder.second;
      this->third = builder.third;
      this->fourth = builder.fourth;
    }
    

    示例

    int main() {
      I::Builder builder;
    
      I i = builder.set_first(100).set_second(102);
      std::cout << "[sample 1] first: " << i.get_first() << "\n";
      std::cout << "[sample 1] second: " << i.get_second() << "\n";
      std::cout << "[sample 1] third: " << i.get_third() << "\n";
      std::cout << "[sample 1] fourth: " << i.get_fourth() << "\n";
      std::cout << "\n";
    
      i = builder.set_first(12).set_second(13).set_third(14).set_fourth(15);
      std::cout << "[sample 2] first: " << i.get_first() << "\n";
      std::cout << "[sample 2] second: " <<  i.get_second() << "\n";
      std::cout << "[sample 2] third: " << i.get_third() << "\n";
      std::cout << "[sample 2] fourth: " << i.get_fourth() << "\n";
      std::cout << "\n";
    
      i = builder.set_first(1).set_third(3);
      std::cout << "[sample 3] first: " << i.get_first() << "\n";
      std::cout << "[sample 3] second: " << i.get_second() << "\n";
      std::cout << "[sample 3] third: " << i.get_third() << "\n";
      std::cout << "[sample 3] fourth: " << i.get_fourth() << "\n";
    
      return 0;
    }
    

    它产生以下输出:

    [sample 1] first: 100
    [sample 1] second: 102
    [sample 1] third: 0
    [sample 1] fourth: 0
    
    [sample 2] first: 12
    [sample 2] second: 13
    [sample 2] third: 14
    [sample 2] fourth: 15
    
    [sample 3] first: 1
    [sample 3] second: 13
    [sample 3] third: 3
    [sample 3] fourth: 15
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-18
      • 2012-07-11
      • 2010-09-23
      相关资源
      最近更新 更多