佛山做外贸网站平台,金坛市住房和城乡建设局 网站,视频素材网站推荐,wordpress 获取首页地址文章目录 一、前言二、为什么需要Builder Pattern,Builder Pattern到底解决了什么实际问题#xff1f;为什么不用set()方法#xff1f;2.1 初学者有那些对象的属性初始化方法呢#xff1f;2.1.1 构造函数的弊端2.1.1.1 对于属性的初始化只能是固定的顺序 2.1.2 用set()函数初… 文章目录 一、前言二、为什么需要Builder Pattern,Builder Pattern到底解决了什么实际问题为什么不用set()方法2.1 初学者有那些对象的属性初始化方法呢2.1.1 构造函数的弊端2.1.1.1 对于属性的初始化只能是固定的顺序 2.1.2 用set()函数初始化类的弊端2.1.2.1 类属性太多类的可读性太差 三、Builder Pattern各种写法的对比3.1 《C20设计模式》中的流式构造器3.1.1 流式构造器3.1.1.1 UML类图3.1.1.2 实现 3.2 传统构造器3.2.1 UML类图3.2.2实现 3.3 组合构造器3.3.1UML类图3.3.2实现 四、总结 一、前言
笔者时刚学习Builder Pattern遇到了很多问题在此汇总一下也希望能帮到你如有错误请指正。
为什么需要Builder Pattern,Builder Pattern到底解决了什么实际问题为什么不用set()方法《C20设计模式》流式构造器到底怎么实现的friend关键字的使用是否必要常规的构造器怎么实现他能解决的问题组合构造器的实现
相关代码可以在这里如有帮助给个starAidenYuanDev/design_patterns_in_modern_Cpp_20
二、为什么需要Builder Pattern,Builder Pattern到底解决了什么实际问题为什么不用set()方法
首先明确一个点Builder Pattern主要是对于对象的属性初始化的研究也就是我们怎么样的方式创建对象才能高内聚低耦合实现更优雅。
2.1 初学者有那些对象的属性初始化方法呢
使用构造函数 —— 属性的初始化只能是固定的顺序创建set()函数初始化函数 —— 类属性太多类的可读性太差
2.1.1 构造函数的弊端
2.1.1.1 对于属性的初始化只能是固定的顺序
重载的特性如果一个构造函数的参数个数参数类型参数顺序一致的话就说他是同一个构造函数
举个例子
class monster {
public:// 这两个构造函数是不能同时出现的编译器会认为他们是同一个函数。monster(string name, int attack_damage, int defense) {_name name;_attack_damage attack_damage;_defense defense;}/*monster(string name, int defense, int attack_damage) {_name name;_attack_damage attack_damage;_defense defense;}
*/private:string _name;int _attack_damage; // 攻击力int _defense; // 防御力
};所以说要想按任意顺序初始化类的属性该怎么办呢没错可以用set()方法
2.1.2 用set()函数初始化类的弊端
2.1.2.1 类属性太多类的可读性太差
注这里用了流式也就是返回类自己的指针主要简化main中初始化过程 举个例子
#include iostream
#include string
#include vector
#include map
#include set
#include listclass Vehicle {
private:// 基本属性std::string make;std::string model;int year;double price;// 动力属性double engineSize;int horsepower;std::string fuelType;// 尺寸和重量double length;double width;double height;double curbWeight;// 车辆特征std::vectorstd::string features;std::mapstd::string, std::string specifications;std::setstd::string safetyFeatures;// 拥有者信息std::liststd::string previousOwners;std::mapstd::string, std::string ownerDetails;public:// 构造函数Vehicle(std::string make, std::string model, int year, double price): make(make), model(model), year(year), price(price) {}// 流式设置方法Vehicle setMake(const std::string make) { this-make make; return *this; }Vehicle setModel(const std::string model) { this-model model; return *this; }Vehicle setYear(int year) { this-year year; return *this; }Vehicle setPrice(double price) { this-price price; return *this; }Vehicle setEngineSize(double engineSize) { this-engineSize engineSize; return *this; }Vehicle setHorsepower(int horsepower) { this-horsepower horsepower; return *this; }Vehicle setFuelType(const std::string fuelType) { this-fuelType fuelType; return *this; }Vehicle setLength(double length) { this-length length; return *this; }Vehicle setWidth(double width) { this-width width; return *this; }Vehicle setHeight(double height) { this-height height; return *this; }Vehicle setCurbWeight(double curbWeight) { this-curbWeight curbWeight; return *this; }Vehicle addFeature(const std::string feature) { features.push_back(feature); return *this; }Vehicle addSpecification(const std::string key, const std::string value) { specifications[key] value; return *this; }Vehicle addSafetyFeature(const std::string feature) { safetyFeatures.insert(feature); return *this; }Vehicle addPreviousOwner(const std::string owner) { previousOwners.push_back(owner); return *this; }Vehicle addOwnerDetail(const std::string key, const std::string value) { ownerDetails[key] value; return *this; }// 获取属性的方法std::string getMake() const { return make; }std::string getModel() const { return model; }int getYear() const { return year; }double getPrice() const { return price; }double getEngineSize() const { return engineSize; }int getHorsepower() const { return horsepower; }std::string getFuelType() const { return fuelType; }double getLength() const { return length; }double getWidth() const { return width; }double getHeight() const { return height; }double getCurbWeight() const { return curbWeight; }std::vectorstd::string getFeatures() const { return features; }std::mapstd::string, std::string getSpecifications() const { return specifications; }std::setstd::string getSafetyFeatures() const { return safetyFeatures; }std::liststd::string getPreviousOwners() const { return previousOwners; }std::mapstd::string, std::string getOwnerDetails() const { return ownerDetails; }// 打印车辆信息的方法void printVehicleInfo() const {std::cout Make: make \nModel: model \nYear: year \nPrice: $ price \n;std::cout Engine Size: engineSize L\nHorsepower: horsepower \nFuel Type: fuelType \n;std::cout Dimensions (LxWxH): length x width x height meters\n;std::cout Curb Weight: curbWeight kg\n;std::cout Features:\n;for (const auto feature : features) {std::cout - feature \n;}std::cout Specifications:\n;for (const auto spec : specifications) {std::cout spec.first : spec.second \n;}std::cout Safety Features:\n;for (const auto safety : safetyFeatures) {std::cout - safety \n;}std::cout Previous Owners:\n;for (const auto owner : previousOwners) {std::cout - owner \n;}std::cout Owner Details:\n;for (const auto detail : ownerDetails) {std::cout detail.first : detail.second \n;}}
};int main() {Vehicle car(Toyota, Camry, 2021, 24000);car.setEngineSize(2.5).setHorsepower(203).setFuelType(Gasoline).setLength(4.88).setWidth(1.84).setHeight(1.45).setCurbWeight(1495).addFeature(Air Conditioning).addFeature(Navigation System).addSpecification(Transmission, 8-speed automatic).addSpecification(Drivetrain, FWD).addSafetyFeature(ABS).addSafetyFeature(Airbags).addPreviousOwner(John Doe).addOwnerDetail(Current Owner, Jane Smith);car.printVehicleInfo();return 0;
}
三、Builder Pattern各种写法的对比
3.1 《C20设计模式》中的流式构造器
流式构造器要明白他的意思要把它分成两部分
构造器就是把set方法从原有的类中拿出来建立一个新类用这个新类构造原来的类实现解耦。流式set()返回值不再是void现在返回类的指针
3.1.1 流式构造器
流式构造器重载Vehicle()就可以省去返回build()步骤这里注意要把流式构造器设置为友元不然访问不了被造的类的私有成员函数。 是否应该使用friend关键字后面讨论friend破坏类的封装到底要不要用应不应该用
3.1.1.1 UML类图 3.1.1.2 实现
#include iostream
#include string
#include vector
#include map
#include set
#include list
#include memoryclass Vehicle {
private:// 基本属性std::string make;std::string model;int year;double price;// 动力属性double engineSize;int horsepower;std::string fuelType;// 尺寸和重量double length;double width;double height;double curbWeight;// 车辆特征std::vectorstd::string features;std::mapstd::string, std::string specifications;std::setstd::string safetyFeatures;// 拥有者信息std::liststd::string previousOwners;std::mapstd::string, std::string ownerDetails;public:// 构造函数Vehicle(const std::string make, const std::string model, int year, double price): make(make), model(model), year(year), price(price), engineSize(0), horsepower(0), length(0), width(0), height(0), curbWeight(0) {}// 打印车辆信息的方法void printVehicleInfo() const {std::cout Make: make \nModel: model \nYear: year \nPrice: $ price \n;std::cout Engine Size: engineSize L\nHorsepower: horsepower \nFuel Type: fuelType \n;std::cout Dimensions (LxWxH): length x width x height meters\n;std::cout Curb Weight: curbWeight kg\n;std::cout Features:\n;for (const auto feature : features) {std::cout - feature \n;}std::cout Specifications:\n;for (const auto spec : specifications) {std::cout spec.first : spec.second \n;}std::cout Safety Features:\n;for (const auto safety : safetyFeatures) {std::cout - safety \n;}std::cout Previous Owners:\n;for (const auto owner : previousOwners) {std::cout - owner \n;}std::cout Owner Details:\n;for (const auto detail : ownerDetails) {std::cout detail.first : detail.second \n;}}// 友元声明允许构建器访问私有成员friend class VehicleBuilder;
};class VehicleBuilder {
private:std::unique_ptrVehicle vehicle;public:// 构造函数VehicleBuilder(const std::string make, const std::string model, int year, double price): vehicle(std::make_uniqueVehicle(make, model, year, price)) {}// 流式设置方法VehicleBuilder setEngineSize(double engineSize) { vehicle-engineSize engineSize; return *this; }VehicleBuilder setHorsepower(int horsepower) { vehicle-horsepower horsepower; return *this; }VehicleBuilder setFuelType(const std::string fuelType) { vehicle-fuelType fuelType; return *this; }VehicleBuilder setLength(double length) { vehicle-length length; return *this; }VehicleBuilder setWidth(double width) { vehicle-width width; return *this; }VehicleBuilder setHeight(double height) { vehicle-height height; return *this; }VehicleBuilder setCurbWeight(double curbWeight) { vehicle-curbWeight curbWeight; return *this; }VehicleBuilder addFeature(const std::string feature) { vehicle-features.push_back(feature); return *this; }VehicleBuilder addSpecification(const std::string key, const std::string value) { vehicle-specifications[key] value; return *this; }VehicleBuilder addSafetyFeature(const std::string feature) { vehicle-safetyFeatures.insert(feature); return *this; }VehicleBuilder addPreviousOwner(const std::string owner) { vehicle-previousOwners.push_back(owner); return *this; }VehicleBuilder addOwnerDetail(const std::string key, const std::string value) { vehicle-ownerDetails[key] value; return *this; }// 类型转换运算符重载operator std::unique_ptrVehicle() { return std::move(vehicle); }
};int main() {std::unique_ptrVehicle car VehicleBuilder(Toyota, Camry, 2021, 24000).setEngineSize(2.5).setHorsepower(203).setFuelType(Gasoline).setLength(4.88).setWidth(1.84).setHeight(1.45).setCurbWeight(1495).addFeature(Air Conditioning).addFeature(Navigation System).addSpecification(Transmission, 8-speed automatic).addSpecification(Drivetrain, FWD).addSafetyFeature(ABS).addSafetyFeature(Airbags).addPreviousOwner(John Doe).addOwnerDetail(Current Owner, Jane Smith);car-printVehicleInfo();return 0;
}
3.2 传统构造器
传统构造器是怎么实现的他的优点是什么 虽然说上一个流式构造器已经非常优秀了但是经典构造器依旧有优点这点见仁见智 方式要创建新的对象就写一个具体的类实现抽象类。 优点
创建一个具体的类后下次就不用创建了直接用就可以提高复用性 。我们可以选择不同的类实现选配的效果
3.2.1 UML类图 3.2.2实现
#include iostream
#include string
#include vector
#include map
#include set
#include list
#include memory// 产品类
class Vehicle {
private:// 基本属性std::string make;std::string model;int year;double price;// 动力属性double engineSize;int horsepower;std::string fuelType;// 尺寸和重量double length;double width;double height;double curbWeight;// 车辆特征std::vectorstd::string features;std::mapstd::string, std::string specifications;std::setstd::string safetyFeatures;// 拥有者信息std::liststd::string previousOwners;std::mapstd::string, std::string ownerDetails;public:// 设置各属性的方法void setMake(const std::string make) { this-make make; }void setModel(const std::string model) { this-model model; }void setYear(int year) { this-year year; }void setPrice(double price) { this-price price; }void setEngineSize(double engineSize) { this-engineSize engineSize; }void setHorsepower(int horsepower) { this-horsepower horsepower; }void setFuelType(const std::string fuelType) { this-fuelType fuelType; }void setLength(double length) { this-length length; }void setWidth(double width) { this-width width; }void setHeight(double height) { this-height height; }void setCurbWeight(double curbWeight) { this-curbWeight curbWeight; }void addFeature(const std::string feature) { features.push_back(feature); }void addSpecification(const std::string key, const std::string value) { specifications[key] value; }void addSafetyFeature(const std::string feature) { safetyFeatures.insert(feature); }void addPreviousOwner(const std::string owner) { previousOwners.push_back(owner); }void addOwnerDetail(const std::string key, const std::string value) { ownerDetails[key] value; }// 打印车辆信息的方法void printVehicleInfo() const {std::cout Make: make \nModel: model \nYear: year \nPrice: $ price \n;std::cout Engine Size: engineSize L\nHorsepower: horsepower \nFuel Type: fuelType \n;std::cout Dimensions (LxWxH): length x width x height meters\n;std::cout Curb Weight: curbWeight kg\n;std::cout Features:\n;for (const auto feature : features) {std::cout - feature \n;}std::cout Specifications:\n;for (const auto spec : specifications) {std::cout spec.first : spec.second \n;}std::cout Safety Features:\n;for (const auto safety : safetyFeatures) {std::cout - safety \n;}std::cout Previous Owners:\n;for (const auto owner : previousOwners) {std::cout - owner \n;}std::cout Owner Details:\n;for (const auto detail : ownerDetails) {std::cout detail.first : detail.second \n;}}
};// 抽象建造者
class VehicleBuilder {
public:virtual ~VehicleBuilder() default;virtual void setMake() 0;virtual void setModel() 0;virtual void setYear() 0;virtual void setPrice() 0;virtual void setEngineSize() 0;virtual void setHorsepower() 0;virtual void setFuelType() 0;virtual void setDimensions() 0;virtual void setCurbWeight() 0;virtual void addFeatures() 0;virtual void addSpecifications() 0;virtual void addSafetyFeatures() 0;virtual void addPreviousOwners() 0;virtual void addOwnerDetails() 0;virtual std::unique_ptrVehicle getVehicle() 0;
};// 具体建造者
class ConcreteVehicleBuilder : public VehicleBuilder {
private:std::unique_ptrVehicle vehicle;public:ConcreteVehicleBuilder() {vehicle std::make_uniqueVehicle();}void setMake() override {vehicle-setMake(Toyota);}void setModel() override {vehicle-setModel(Camry);}void setYear() override {vehicle-setYear(2021);}void setPrice() override {vehicle-setPrice(24000);}void setEngineSize() override {vehicle-setEngineSize(2.5);}void setHorsepower() override {vehicle-setHorsepower(203);}void setFuelType() override {vehicle-setFuelType(Gasoline);}void setDimensions() override {vehicle-setLength(4.88);vehicle-setWidth(1.84);vehicle-setHeight(1.45);}void setCurbWeight() override {vehicle-setCurbWeight(1495);}void addFeatures() override {vehicle-addFeature(Air Conditioning);vehicle-addFeature(Navigation System);}void addSpecifications() override {vehicle-addSpecification(Transmission, 8-speed automatic);vehicle-addSpecification(Drivetrain, FWD);}void addSafetyFeatures() override {vehicle-addSafetyFeature(ABS);vehicle-addSafetyFeature(Airbags);}void addPreviousOwners() override {vehicle-addPreviousOwner(John Doe);}void addOwnerDetails() override {vehicle-addOwnerDetail(Current Owner, Jane Smith);}std::unique_ptrVehicle getVehicle() override {return std::move(vehicle);}
};// 指挥者类
class Director {
private:VehicleBuilder* builder;public:void setBuilder(VehicleBuilder* builder) {this-builder builder;}std::unique_ptrVehicle construct() {builder-setMake();builder-setModel();builder-setYear();builder-setPrice();builder-setEngineSize();builder-setHorsepower();builder-setFuelType();builder-setDimensions();builder-setCurbWeight();builder-addFeatures();builder-addSpecifications();builder-addSafetyFeatures();builder-addPreviousOwners();builder-addOwnerDetails();return builder-getVehicle();}
};// 主函数
int main() {Director director;ConcreteVehicleBuilder builder;director.setBuilder(builder);std::unique_ptrVehicle car director.construct();car-printVehicleInfo();return 0;
}
3.3 组合构造器
个人觉得这个依然是巅峰了当时第一次看到这个实现方式真的是惊为天人
优点可以选配特定一类属性进行初始化再也不用担心到不到要初始化的类了
3.3.1UML类图 3.3.2实现
#include algorithm
#include iostream
#include list
#include vector
#include map
#include set
#include memory
using namespace std;class Vehicle_Builder;
class V_Basic_Properties_Builder;
class V_Dynamic_Properties_Builder;
class V_Size_And_Weight_Builder;
class V_Vehicle_Features_Builder;
class V_Owner_Information_Builder;class Vehicle {
private:// 基本属性std::string make;std::string model;int year;double price;// 动力属性double engineSize;int horsepower;std::string fuelType;// 尺寸和重量double length;double width;double height;double curbWeight;// 车辆特征std::vectorstd::string features;std::mapstd::string, std::string specifications;std::setstd::string safetyFeatures;// 拥有者信息std::liststd::string previousOwners;std::mapstd::string, std::string ownerDetails;public:static Vehicle_Builder create();Vehicle(){}// 打印车辆信息的方法void printVehicleInfo() const {std::cout 制造商: make \n型号: model \n年份: year \n价格: $ price \n;std::cout 发动机大小: engineSize L\n马力: horsepower \n燃料类型: fuelType \n;std::cout 尺寸 (长x宽x高): length x width x height 米\n;std::cout 整备质量: curbWeight 千克\n;std::cout 特征:\n;for (const auto feature : features) {std::cout - feature \n;}std::cout 规格:\n;for (const auto spec : specifications) {std::cout spec.first : spec.second \n;}std::cout 安全特征:\n;for (const auto safety : safetyFeatures) {std::cout - safety \n;}std::cout 之前的车主:\n;for (const auto owner : previousOwners) {std::cout - owner \n;}std::cout 车主详细信息:\n;for (const auto detail : ownerDetails) {std::cout detail.first : detail.second \n;}}// 友元声明允许构建器访问私有成员friend class Vehicle_Builder;friend class V_Basic_Properties_Builder;friend class V_Dynamic_Properties_Builder;friend class V_Size_And_Weight_Builder;friend class V_Vehicle_Features_Builder;friend class V_Owner_Information_Builder;
};class Vehicle_Builder_Base {
protected:Vehicle vehicle;explicit Vehicle_Builder_Base(Vehicle vehicle) : vehicle(vehicle) {}public:operator Vehicle() { return std::move(vehicle); }V_Basic_Properties_Builder basic_properties() const;V_Dynamic_Properties_Builder dynamic_properties() const;V_Size_And_Weight_Builder size_and_weight() const;V_Vehicle_Features_Builder vehicle_features() const;V_Owner_Information_Builder owner_information() const;
};class Vehicle_Builder : public Vehicle_Builder_Base {
protected:Vehicle vehicle;
public:Vehicle_Builder() : Vehicle_Builder_Base(vehicle) {}
};class V_Basic_Properties_Builder : public Vehicle_Builder_Base {
public:explicit V_Basic_Properties_Builder(Vehicle vehicle) : Vehicle_Builder_Base(vehicle) {}V_Basic_Properties_Builder make(const std::string make) {vehicle.make make;return *this;}V_Basic_Properties_Builder model(const std::string model) {vehicle.model model;return *this;}V_Basic_Properties_Builder year(int year) {vehicle.year year;return *this;}V_Basic_Properties_Builder price(double price) {vehicle.price price;return *this;}
};class V_Dynamic_Properties_Builder : public Vehicle_Builder_Base {
public:explicit V_Dynamic_Properties_Builder(Vehicle vehicle) : Vehicle_Builder_Base(vehicle) {}V_Dynamic_Properties_Builder engineSize(double engineSize) {vehicle.engineSize engineSize;return *this;}V_Dynamic_Properties_Builder horsepower(int horsepower) {vehicle.horsepower horsepower;return *this;}V_Dynamic_Properties_Builder fuelType(const std::string fuelType) {vehicle.fuelType fuelType;return *this;}
};class V_Size_And_Weight_Builder : public Vehicle_Builder_Base {
public:explicit V_Size_And_Weight_Builder(Vehicle vehicle) : Vehicle_Builder_Base(vehicle) {}V_Size_And_Weight_Builder length(double length) {vehicle.length length;return *this;}V_Size_And_Weight_Builder width(double width) {vehicle.width width;return *this;}V_Size_And_Weight_Builder height(double height) {vehicle.height height;return *this;}V_Size_And_Weight_Builder curbWeight(double curbWeight) {vehicle.curbWeight curbWeight;return *this;}
};class V_Vehicle_Features_Builder : public Vehicle_Builder_Base {
public:explicit V_Vehicle_Features_Builder(Vehicle vehicle) : Vehicle_Builder_Base(vehicle) {}V_Vehicle_Features_Builder addFeature(const std::string feature) {vehicle.features.push_back(feature);return *this;}V_Vehicle_Features_Builder addSpecification(const std::string key, const std::string value) {vehicle.specifications[key] value;return *this;}V_Vehicle_Features_Builder addSafetyFeature(const std::string safetyFeature) {vehicle.safetyFeatures.insert(safetyFeature);return *this;}
};class V_Owner_Information_Builder : public Vehicle_Builder_Base {
public:explicit V_Owner_Information_Builder(Vehicle vehicle) : Vehicle_Builder_Base(vehicle) {}V_Owner_Information_Builder addPreviousOwner(const std::string owner) {vehicle.previousOwners.push_back(owner);return *this;}V_Owner_Information_Builder addOwnerDetail(const std::string key, const std::string value) {vehicle.ownerDetails[key] value;return *this;}
};Vehicle_Builder Vehicle::create() {return Vehicle_Builder();
}V_Basic_Properties_Builder Vehicle_Builder_Base::basic_properties() const {return V_Basic_Properties_Builder(vehicle);
}V_Dynamic_Properties_Builder Vehicle_Builder_Base::dynamic_properties() const {return V_Dynamic_Properties_Builder(vehicle);
}V_Size_And_Weight_Builder Vehicle_Builder_Base::size_and_weight() const {return V_Size_And_Weight_Builder(vehicle);
}V_Vehicle_Features_Builder Vehicle_Builder_Base::vehicle_features() const {return V_Vehicle_Features_Builder(vehicle);
}V_Owner_Information_Builder Vehicle_Builder_Base::owner_information() const {return V_Owner_Information_Builder(vehicle);
}int main() {Vehicle vehicle Vehicle::create().basic_properties().make(丰田).model(凯美瑞).year(2020).price(30000.0).dynamic_properties().engineSize(2.5).horsepower(203).fuelType(汽油).size_and_weight().length(4.8).width(1.8).height(1.4).curbWeight(1500).vehicle_features().addFeature(天窗).addSpecification(变速器, 自动).addSafetyFeature(ABS).owner_information().addPreviousOwner(约翰·多伊).addOwnerDetail(当前车主, 简·多伊);vehicle.printVehicleInfo();return 0;
}
四、总结
对于这三种构造器我还是喜欢组合和流式因为个人觉得他是真正做到把对象的创建和对象的使用分离开来的
对于friend关键字我平时也是可以用的不过要更加深思熟虑破坏封装性也是真的但也不是不用这个C存在的特性。
最后作者也是刚学写下对此设计模式的疑惑如有错误请指正 点个赞吧