本文主要是介绍C++使用内部类实现一种Builder模式(属性内容不对外暴露, 不需管理指针),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
假设我们有一个生产车的工厂,每辆车有如下属性: 系列、颜色、载人数
头文件如下:
#ifndef TEST_H
#define TEST_H#include <string>
#include <memory>using namespace std;class Car
{
public:class Builder{public:Builder(const Builder &builderArg);Builder(const Builder &&builderArg);Builder& operator=(const Builder &builderArg);Builder& operator=(const Builder &&builderArg);Builder(const string &series);Builder& setColor(const string &color); Builder& setSize(const int size); Car build();private:shared_ptr<void> carBuildData;friend class Car;};void drive();Car() = default;~Car() = default;Car(const Builder &builder);Car(const Car &carArg);Car(const Car &&carArg);Car& operator=(const Car &carArg);Car& operator=(const Car &&carArg);private:shared_ptr<void> carData;
};#endif // !TEST_H
用shared_ptr<void>
的目的在于希望内部数据隐藏,对外不体现。
实现如下:
#include "test.h"
#include <iostream>
#include <functional>struct CarData_t{string series; // 系列string color = "RED"; // 颜色int size = 5; // 大小(载人数)CarData_t(const string &seriesArg) : series(seriesArg) {}
};Car::Builder::Builder(const Car::Builder &builderArg)
{carBuildData = builderArg.carBuildData;
}Car::Builder::Builder(const Car::Builder &&builderArg)
{carBuildData = builderArg.carBuildData;
}Car::Builder& Car::Builder::operator=(const Car::Builder &builderArg)
{carBuildData = builderArg.carBuildData;return *this;
}Car::Builder& Car::Builder::operator=(const Car::Builder &&builderArg)
{carBuildData = builderArg.carBuildData;return *this;
}Car::Car(const Car &carArg)
{carData = carArg.carData;
}Car::Car(const Car &&carArg)
{carData = carArg.carData;
}Car& Car::operator=(const Car &carArg)
{carData = carArg.carData;return *this;
}Car& Car::operator=(const Car &&carArg)
{carData = carArg.carData;return *this;
}Car::Builder::Builder(const string &series)
{CarData_t testdata(series);carBuildData = make_shared<CarData_t>(testdata);
}Car Car::Builder::build()
{Car test(*this);// 这里直接返回, 函数返回值Car未加&,会触发移动构造函数,如果返回值为Car&,会触发拷贝构造函数return test;
}// 减少重复造轮子,每个set函数都要判断指针是否为空,用回调可以避免重复判断
void operateTestDataArg(void* testDataVoidPtr, function<void(CarData_t*)> callback)
{if (testDataVoidPtr == nullptr) { return; }auto testDataPtr = reinterpret_cast<CarData_t*>(testDataVoidPtr);if (testDataPtr == nullptr) {return;}callback(testDataPtr);
}void Car::drive()
{operateTestDataArg(carData.get(), [&](CarData_t* testDataPtr) {cout << "series : " << testDataPtr->series << " ";cout << "color : " << testDataPtr->color << " ";cout << "size : " << testDataPtr->size << endl;});
}Car::Car(const Builder &builder)
{operateTestDataArg(builder.carBuildData.get(), [&](CarData_t* buildDataPtr) {carData = make_shared<CarData_t>(*buildDataPtr);});
}Car::Builder& Car::Builder::setColor(const string &color)
{operateTestDataArg(carBuildData.get(), [&](CarData_t* buildDataPtr) {buildDataPtr->color = color;});return *this;
}Car::Builder& Car::Builder::setSize(const int size)
{operateTestDataArg(carBuildData.get(), [&](CarData_t* buildDataPtr) {buildDataPtr->size = size;});return *this;
}
下面来使用:
int main()
{auto benz = Car::Builder("Benz").build();cout << "1 : Benz "; benz.drive();// 设置benz为公司用车,由于实现了赋值运算符函数,使用了shared_ptr, benz析构后CompanyCar也能继续使用,CompanyCar和benz中的carData指向同一片空间,对于shared_ptr来说,指向该空间的指针均析构了后该空间才会自动释放auto CompanyCar = benz;cout << "2 : CompanyCar "; CompanyCar.drive();auto HondaBaseBuilder = Car::Builder("Honda");Car HondaDefault(HondaBaseBuilder);cout << "3 : HondaDefault "; HondaDefault.drive();auto HondaBlue = HondaBaseBuilder.setColor("Blue").setSize(5).build();cout << "4 : HondaBlue "; HondaBlue.drive();auto HondaSmallBlack = HondaBaseBuilder.setColor("Black").setSize(2).build();cout << "5 : HondaSmallBlack "; HondaSmallBlack.drive();// ps:HondaBaseBuilder属性一直在变 此时初始化car已经不是默认值了,可以自己加入reset函数扩展 或者重新设置属性,此处功能为保证为Honda系列,不用重复Builder("Honda")Car HondaCurrent(HondaBaseBuilder);cout << "5 : HondaCurrent "; HondaCurrent.drive();return 0;
}
运行结果:
1 : Benz series : Benz color : RED size : 5
2 : CompanyCar series : Benz color : RED size : 5
3 : HondaDefault series : Honda color : RED size : 5
4 : HondaBlue series : Honda color : Blue size : 5
5 : HondaSmallBlack series : Honda color : Black size : 2
5 : HondaCurrent series : Honda color : Black size : 2
这篇关于C++使用内部类实现一种Builder模式(属性内容不对外暴露, 不需管理指针)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!