构造器模式可以简化复杂对象或一系列对象的构造过程,从而单独定义构成该复杂对象的各个组件的构建方法。
这篇文章只讲解较为简单的构造器的创建。创建一个构造器我们得了解如何实现流式调用以及如何关闭外界的访问权对构造函数的访问权限。
流式调用
所谓流式调用就是能实现在一行代码中连续调用多个函数的效果,具体效果如下:
Object obj;
obj.call("流").call("式").call("调").call("用");
而实现这种技术的方式很简单,就是让函数返回对象自身或者对象自身的指针,也就是*this
或者this
,具体实现如下:
class object {Object& call(string str) {// ...return *this;}
};
关闭构造函数访问权限
在构造器设计模式中,因为我们会提供专门的构造器供对象使用者创建对象,有时我们会不希望使用者跳过构造器直接使用构造函数构造,所以我们会选择将封闭构造函数。封闭构造函数的方式很简单,就是将构造函数设置为 protected 或者 private,如果你希望这个类未来可以被继承,那么就设置为 protected,否则可以设置为 private。由于对象封闭构造函数之后,构造器也无法创建该对象,我们需要给构造器一定的特权访问私有或保护的构造函数,我们需要将使用 friend class 构造器类设置为友元类。
构造器
假设我们存在下面的 Vec 类:
#include <string>
#include <vector>
#include <numeric>
#include <iostream>using namespace std;class Vec {vector<string> elements;
public:Vec& add_element(const string& element) {elements.emplace_back(element);return *this;}string str() {return accumulate(elements.begin(), elements.end(), string());}
};
这个类知识简单得封装了 elemnets 字符串容器对象,提供了流式调用填充容器的方法以及将容器对象转字符串的方法。我们会直接创建一个对象并使用它。
int main() {Vec vec;vec.add_element("流").add_element("式").add_element("调").add_element("用");cout << vec.str() << endl;
}
而使用构造器来创建会是怎样的呢?我们会在 Vec 类中提供一个静态方法 build 用于创建 Builder 类,然后将填充容器的工作交给 Builder 类,并在 Builder 类中提供转换函数,便于将 Builder 类隐式转换回为 Vec,那么我们的调用就会变成下面这样:
int main() {Vec vec = Vec::build().add_element("流").add_element("式").add_element("调").add_element("用");cout << vec.str() << endl;
}
这样看起来可能会有点造作,因为这个例子的构造比较简单并不能体现 Builder 的作用,但是简单的例子便于理解 Builder 的写法。下面我们具体介绍 Builder 的创建。
首先,我们需要修改 Vec 类,封闭构造函数的访问权限并提供静态方法用于构建 Builder:
class Vec {
public:vector<string> elements;// 静态方法返回 Builderstatic Builder& build();string str() {return accumulate(elements.begin(), elements.end(), string());}
protected:Vec() = default;// 友元 Builderfriend class Builder;
};//class Builder {
// ...
//}Builder& Vec::build() {Builder* builder = new Builder();return *builder;
}
然后是 Builder 类的构建:
class Builder {
public:Vec vec;// 转换函数operator Vec() const {return vec;}// 填充容器Builder& add_element(const string& element) {vec.elements.emplace_back(element);return *this;}
};
上面 Builder 类首先创建 Vec 类对象,然后提供 add_element 供用户填充 Vec 容器,最后使用 operator Vec() 将 Builder 隐式转换回 Vec 对象。
以上就是简单构造器模式的全部的实现了。
如果想要了解更复杂的构造器如何实现,可以查看 GitHub 仓库 GnCDesignPattern 的代码