【问题标题】:C++ instantiate an object through builderC++通过builder实例化一个对象
【发布时间】:2020-05-08 13:02:03
【问题描述】:

我最近在学习设计模式,我看过关于构建器模式的文章,https://riptutorial.com/cplusplus/example/30166/builder-pattern-with-fluent-api。我对对象的实例化有疑问。下面是文章里面的代码:

#include <iostream>
#include <sstream>
#include <string>

using namespace std;

// Forward declaring the builder
class EmailBuilder;

class Email
{
  public:
    friend class EmailBuilder;  // the builder can access Email's privates

    static EmailBuilder make();

    string to_string() const {
        stringstream stream;
        stream << "from: " << m_from
               << "\nto: " << m_to
               << "\nsubject: " << m_subject
               << "\nbody: " << m_body;
        return stream.str();
    }

  private:
    Email() = default; // restrict construction to builder

    string m_from;
    string m_to;
    string m_subject;
    string m_body;
};

class EmailBuilder
{
  public:
    EmailBuilder& from(const string &from) {
        m_email.m_from = from;
        return *this;
    }

    EmailBuilder& to(const string &to) {
        m_email.m_to = to;
        return *this;
    }

    EmailBuilder& subject(const string &subject) {
        m_email.m_subject = subject;
        return *this;
    }

    EmailBuilder& body(const string &body) {
        m_email.m_body = body;
        return *this;
    }

    operator Email&&() {
        return std::move(m_email); // notice the move
    }

  private:
    Email m_email;
};

EmailBuilder Email::make()
{
    return EmailBuilder();
}

// Bonus example!
std::ostream& operator <<(std::ostream& stream, const Email& email)
{
    stream << email.to_string();
    return stream;
}


int main()
{
    Email mail = Email::make().from("me@mail.com")
                              .to("you@mail.com")
                              .subject("C++ builders")
                              .body("I like this API, don't you?");

    cout << mail << endl;
}

谁能解释一下Email mail = Email::make().from("me@mail.com"),它是如何工作的?

【问题讨论】:

  • "有人能解释一下Email mail = Email::make().from("me@mail.com"),它是如何工作的吗?" 关于它,你不清楚什么?

标签: c++ oop design-patterns


【解决方案1】:

我们来看一下语句:

Email mail = Email::make().from("me@mail.com");

在第一部分,我们调用Email::make(),这会返回一个新的临时EmailBuilder。这个对象负责填充一个Email,它是它的一个私有成员。我们可以填充Email 的内部,因为它是一个friend 类(应该谨慎使用!!不要滥用它!)。

现在,我们调用成员方法from,它填充Emailm_form 成员,并返回 EmailBuilder。这是为了允许使用EmailBuilder的函数的串联使用,例如:

Email mail = Email::make().from("me@mail.com").to("other@mail.com");

是一个有效命令,它同时填充 from 和 to 字段(这种用法很常见)。

最后,我们有了operator Email&amp;&amp;()。这是EmailBuilder 到右值引用Email强制转换运算符。这会将我们创建的内部Email 移动到外部,允许抓取Email 的内部结构到Email mail。这就是将此构建器转换为实际邮件的“魔法”发生的地方。

【讨论】:

    【解决方案2】:

    Email::make() 返回一个 Email 的新实例,它被 from() 修改(实际上是它的成员 m_email),它返回实例的引用,允许它再次被 to() 等修改,最后定义转换的运算符允许获取EmailEmailBuilder 的实例是一个临时变量。注意friend class EmailBuilder 允许EmailBuilder 访问/修改Email 的私有字段

    如果to() 等不返回对实例的引用,则您无法通过管道进行修改,并且必须先保存EmailBuilder 的实例,以便稍后在其上应用from()

    cout &lt;&lt; mail &lt;&lt; endl;也是一样,你可以通过管道传递&lt;&lt;,因为operator &lt;&lt;返回的是std::ostream的实例,但是那个时候没有临时变量。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-09-15
      • 2018-12-13
      • 2018-05-07
      • 1970-01-01
      • 1970-01-01
      • 2013-04-02
      • 2011-07-02
      • 1970-01-01
      相关资源
      最近更新 更多