在C++中,构造器(Builder)模式的思考(《C++20设计模式》及常规设计模式对比)

文章目录

  • 一、前言
  • 二、为什么需要`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 《C++20设计模式》中的流式构造器
      • 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()方法?
  • 《C++20:设计模式》流式构造器到底怎么实现的?friend关键字的使用是否必要?
  • 常规的构造器怎么实现?他能解决的问题?
  • 组合构造器的实现?

相关代码可以在这里,如有帮助给个star!AidenYuanDev/design_patterns_in_modern_Cpp_20

二、为什么需要Builder Pattern,Builder Pattern到底解决了什么实际问题?为什么不用set()方法?

首先明确一个点,Builder Pattern主要是对于对象的属性初始化的研究,也就是我们怎么样的方式创建对象才能高内聚,低耦合,实现更优雅。

2.1 初学者有那些对象的属性初始化方法呢?

  1. 使用构造函数 —— 属性的初始化只能是固定的顺序
  2. 创建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 <list>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::vector<std::string> features;std::map<std::string, std::string> specifications;std::set<std::string> safetyFeatures;// 拥有者信息std::list<std::string> previousOwners;std::map<std::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::vector<std::string> getFeatures() const { return features; }std::map<std::string, std::string> getSpecifications() const { return specifications; }std::set<std::string> getSafetyFeatures() const { return safetyFeatures; }std::list<std::string> getPreviousOwners() const { return previousOwners; }std::map<std::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 《C++20设计模式》中的流式构造器

流式构造器要明白他的意思要把它分成两部分:

  • 构造器:就是把set方法从原有的类中拿出来,建立一个新类,用这个新类构造原来的类,实现解耦。
  • 流式set()返回值不再是void,现在返回类的指针

3.1.1 流式构造器

  • 流式构造器重载Vehicle(),就可以省去返回build()步骤
  • 这里注意要把流式构造器设置为(友元),不然访问不了被造的类的私有成员函数。

    是否应该使用friend关键字,后面讨论(friend破坏类的封装,到底要不要用,应不应该用?)

3.1.1.1 UML类图

流式构造器UML类图

3.1.1.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::vector<std::string> features;std::map<std::string, std::string> specifications;std::set<std::string> safetyFeatures;// 拥有者信息std::list<std::string> previousOwners;std::map<std::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_ptr<Vehicle> vehicle;public:// 构造函数VehicleBuilder(const std::string& make, const std::string& model, int year, double price): vehicle(std::make_unique<Vehicle>(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_ptr<Vehicle>() { return std::move(vehicle); }
};int main() {std::unique_ptr<Vehicle> 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类图

经典构造器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::vector<std::string> features;std::map<std::string, std::string> specifications;std::set<std::string> safetyFeatures;// 拥有者信息std::list<std::string> previousOwners;std::map<std::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_ptr<Vehicle> getVehicle() = 0;
};// 具体建造者
class ConcreteVehicleBuilder : public VehicleBuilder {
private:std::unique_ptr<Vehicle> vehicle;public:ConcreteVehicleBuilder() {vehicle = std::make_unique<Vehicle>();}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_ptr<Vehicle> getVehicle() override {return std::move(vehicle);}
};// 指挥者类
class Director {
private:VehicleBuilder* builder;public:void setBuilder(VehicleBuilder* builder) {this->builder = builder;}std::unique_ptr<Vehicle> 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_ptr<Vehicle> car = director.construct();car->printVehicleInfo();return 0;
}

3.3 组合构造器

个人觉得这个依然是巅峰了,当时第一次看到这个实现方式真的是惊为天人!

优点:可以选配(特定一类属性进行初始化,再也不用担心到不到要初始化的类了!)

3.3.1UML类图

组合构造器UML类图

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::vector<std::string> features;std::map<std::string, std::string> specifications;std::set<std::string> safetyFeatures;// 拥有者信息std::list<std::string> previousOwners;std::map<std::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++存在的特性。

最后!作者也是刚学,写下对此设计模式的疑惑,如有错误,请指正!
点个赞吧!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/858450.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

兰州理工大学24计算机考研情况,好多专业都接受调剂,只有计算机专硕不接收调剂,复试线为283分!

兰州理工大学&#xff08;Lanzhou University of Technology&#xff09;&#xff0c;位于甘肃省兰州市&#xff0c;是甘肃省人民政府、教育部、国家国防科技工业局共建高校&#xff0c;甘肃省高水平大学和“一流学科”建设高校&#xff1b;入选国家“中西部高校基础能力建设工…

redis主从复制、哨兵、集群

在实际的生活环境中&#xff0c;如果只使用一个redis进行读写操作&#xff0c;那么面对庞大的访问人群是崩溃的&#xff0c;所以可以有几个redis&#xff0c;一个用来做主机&#xff0c;提供修改数据操作&#xff0c;而这个主机用来控制其他redis&#xff0c;即将更新的发送&am…

Windows程序设计课程作业-3(文件并发下载)

目录 目录 1.作业内容 2.作业要求 3.主要思路 1&#xff09;窗体和组件初始化 2&#xff09;下载管理器实例化 3&#xff09;按钮点击事件处理 4&#xff09;窗体加载事件处理 5&#xff09;下载消息处理 4.主要难点 1&#xff09;多线程管理&#xff1a; 2&#xff09…

材料科学SCI期刊,中科院3区,收稿范围广,易录用

一、期刊名称 International Journal of Material Forming 二、期刊简介概况 期刊类型&#xff1a;SCI 学科领域&#xff1a;材料科学 影响因子&#xff1a;2.4 中科院分区&#xff1a;3区 三、期刊征稿范围 该杂志发表和传播材料成型领域的原创研究。该研究应构成对材料…

理解广角镜头的视野和畸变

为什么广角镜头的视野会比长焦镜头的视野大呢&#xff1f; 我之前用等光程解释了景深&#xff0c;也解释了为什么焦距越远&#xff0c;成像越大&#xff0c;但是从来没有提到过视野范围这个概念。实际上在我之前建立的数学模型中&#xff0c;物曲面S是无限大的&#xff0c;像曲…

Chromium 调试指南2024 - 远程开发(下)

1. 引言 在《Chromium 调试指南2024 - 远程开发&#xff08;上&#xff09;》中&#xff0c;我们探讨了远程开发的基本概念、优势以及如何选择合适的远程开发模式。掌握了这些基础知识后&#xff0c;接下来我们将深入了解如何在远程环境中高效地进行Chromium项目的调试工作。 …

鹅算法(GOOSE Algorithm,GOOSE)求解复杂城市地形下无人机避障三维航迹规划,可以修改障碍物及起始点(Matlab代码)

一、鹅算法 鹅优化算法&#xff08;GOOSE Algorithm&#xff0c;GOOSE)从鹅的休息和觅食行为获得灵感&#xff0c;当鹅听到任何奇怪的声音或动作时&#xff0c;它们会发出响亮的声音来唤醒群中的个体&#xff0c;并保证它们的安全。 参考文献 [1]Hamad R K, Rashid T A. GOO…

数据结构和算法(1) ---- Queue 的原理和实现

Queue 的定义和结构 队列(Queue) 是只允许在一端进行插入&#xff0c;在另一端进行删除的线性表 队列是一种先进先出(First In First Out)的线性表&#xff0c;简称 FIFO(First IN First OUT), 允许插入的一端称为队尾, 允许删除的一端称为队列头 队列的基本结构如下图所示&a…

FreeCAD中智能指针分析

实现原理 FreeCAD中有两套智能指针&#xff0c;一个是OCC的智能指针handle&#xff0c;另一个是自己定义的智能指针Reference&#xff0c;两种智能指针都是通过引用计数方式管理指针。 1.1 OCC智能指针handle OCC在基础类包中定义了一个模板类handle&#xff0c;该类包含一个私…

大学物理(下)笔记

摘录来自笔记网站的笔记。笔记网站详见https://onford.github.io/Notes/。 大学物理&#xff08;下&#xff09;笔记 部分常用物理常量的计算值 C h a p t e r 9 Chapter9 Chapter9 恒定磁场 毕奥-萨伐尔定律 磁场和电场在很多性质上是有共性的&#xff0c;很多时候可以拿它…

【pytorch05】索引与切片

索引 a[0,0]第0张图片的第0个通道 a[0,0,2,4]第0张图片&#xff0c;第0个通道&#xff0c;第2行&#xff0c;第4列的像素点&#xff0c;dimension为0的标量 选择前/后N张图片 a[:2,:1,:,:].shape前两张图片&#xff0c;第1个通道上的所有图片的数据 a[:2,1:,:,:].shape前两张…

ADD属性驱动架构设计(一)

目录 一、架构设计过程 1.1、架构设计过程 1.1.1、设计目的 1.1.2、质量属性&#xff08;非功能需求&#xff09; 1.1.3、核心功能&#xff08;功能需求&#xff09; 1.1.4、架构关注 1.1.5、约束条件 1.2、基于设计过程 二、什么是ADD? 三、为什么选择ADD? 四、作…

本地离线模型搭建指南-中文大语言模型底座选择依据

搭建一个本地中文大语言模型&#xff08;LLM&#xff09;涉及多个关键步骤&#xff0c;从选择模型底座&#xff0c;到运行机器和框架&#xff0c;再到具体的架构实现和训练方式。以下是一个详细的指南&#xff0c;帮助你从零开始构建和运行一个中文大语言模型。 本地离线模型搭…

鸿蒙开发系统基础能力:【@ohos.hiAppEvent (应用打点)】

应用打点 本模块提供了应用事件打点能力&#xff0c;包括对打点数据的落盘&#xff0c;以及对打点功能的管理配置。 说明&#xff1a; 本模块首批接口从API version 7开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。 导入模块 import hiAppEve…

今日分享:中国石油年金系统交互、视觉设计和vue开发

金融系统交互及UI设计时&#xff0c;需注意简洁明了、色彩合理、字体统一、交互易用、安全感和用户控制。确保用户快速理解、安全操作并提升体验。

数据结构~~时间、空间复杂度

目录 一、什么是数据结构 什么是算法 算法的复杂度 二、时间复杂度 三、空间复杂度 四、总结 一、什么是数据结构 数据结构(Data Structure)是计算机存储、组织数据的方式&#xff0c;指相互之间存在一种或多种特定关系的 数据元素的集合。 数据结构关注的是数据的逻辑结…

快速搭建Jenkins自动化集成cicd工具

一、简介 jenkins是一款优秀的自动化持续集成运维工具&#xff0c;可以极大的简化运维部署的步骤。 传统的项目部署需要手动更换最新的项目代码&#xff0c;然后打包并运行到服务器上。 使用Jenkins可以自动化实现&#xff0c;当代码编写完成并提交到git后&#xff0c;Jenki…

通过 cloudflare 白嫖个人 docker 镜像加速服务

不知为何&#xff0c;现在大多数的 docker hub 镜像加速站都停止服务&#xff0c;而官方站点又因某些原因访问不到或延迟很高。所以&#xff0c;今天来记录一种通过 CloudFlare 搭建一个自己的镜像加速服务。 0、必看&#xff01;&#xff01;&#xff01; 注意&#xff1a; 此…

pywebview打包本地的html

51.安装 pip install pywebview 2.新建start.py import webview import timeclass API:def say_hello(self, name):time.sleep(2) # 模拟一个耗时操作return fHello, {name}!def main():api API()webview.create_window(pywebview Example, index.html, js_apiapi)webview.…

抛弃Mybatis,拥抱新的ORM 框架!【送源码】

背景 转java后的几年时间里面一直在寻找一个类似.net的orm&#xff0c;不需要很特别的功能&#xff0c;仅希望90%的场景都可以通过强类型语法来编写符合直觉的sql&#xff0c;来操作数据库编写业务。 但是一直没有找到&#xff0c;Mybatis-Plus的单表让我在最初的时间段内看到…