C++设计模式:建造者模式

发布于:2025-08-19 ⋅ 阅读:(16) ⋅ 点赞:(0)

建造者模式(Builder Pattern)是一种创建型设计模式,它将一个复杂对象的构建与它的表示分离,通过分步构建的方式创建对象,使得同样的构建过程可以创建不同的表示

建造者模式有四个主要角色,分别是产品(Product)抽象建造者(Builder)具体建造者(Concrete Builder)指挥者(Director)

  • 产品:需要创建的复杂对象。
  • 抽象建造者:定义构建产品的抽象步骤。
  • 具体建造者:实现抽象步骤,负责具体产品的部件创建和组装。
  • 指挥者:控制构建流程的顺序,调用建造者的步骤完成对象创建。
  • 目的:将复杂对象的创建过程封装起来,使得创建过程更加清晰、易于维护,同时也方便对创建过程进行扩展和修改。并且可以根据不同的具体建造者,创建出不同类型的产品。
  • 创建复杂对象:当一个对象的创建过程比较复杂,需要多个步骤来完成,并且这些步骤的组合方式可能会发生变化时,适合使用建造者模式。
  • 创建不同类型的对象:如果需要根据不同的需求创建不同类型的对象,且这些对象的创建过程有相似之处,可以使用建造者模式,通过不同的具体建造者来创建不同类型的对象。

C++订单系统demo:

数据库上层抽象:

class OrderDAO {
public:
    // 根据订单ID查询订单类型
    static string getOrderType(const string& orderId) {
        // 实际实现:执行SQL查询订单类型
    }

    // 根据订单ID查询用户信息
    static string getUserIdByOrderId(const string& orderId) {
        // 实际实现:JOIN查询获取用户ID     
    }

    // 根据订单ID查询商品信息
    static vector<pair<string, double>> getProductsByOrderId(const string& orderId) {
        // 实际实现:查询order_items表
    }

    // 根据订单ID查询优惠券信息
    static pair<string, double> getCouponByOrderId(const string& orderId) {
        // 实际实现:查询优惠券关联表      
    }

    // 根据订单ID查询物流信息
    static pair<string, string> getLogisticsByOrderId(const string& orderId) {
        // 实际实现:查询物流表     
};

业务处理逻辑:

#include <iostream>
#include <string>
#include <vector>
#include <ctime>
using namespace std;

// 辅助类:用户、商品、优惠券、物流信息
class User {
public:
    string userId;
    User(string id) : userId(id) {}
};

class Product {
public:
    string productId;
    double price;
    Product(string id, double p) : productId(id), price(p) {}
};

class Coupon {
public:
    string couponId;
    double discount;
    Coupon(string id, double d) : couponId(id), discount(d) {}
};

class Logistics {
public:
    string logisticsId;
    string company;
    Logistics(string id, string c) : logisticsId(id), company(c) {}
};

// 产品类:订单(复杂对象)
class Order {
private:
    string orderId;        // 必选
    string orderType;      // 订单类型
    User user;             // 必选
    vector<Product> items; // 必选
    Coupon* coupon;        // 可选
    Logistics* logistics;  // 可选

public:
    // 构造函数:初始化必选参数和订单类型
    Order(string oid, string type, User u, vector<Product> i)
        : orderId(oid), orderType(type), user(u), items(i), coupon(nullptr), logistics(nullptr) {}

    // 设置可选参数
    void setCoupon(Coupon* c) { coupon = c; }
    void setLogistics(Logistics* l) { logistics = l; }

    // 展示订单信息
    void show() {
        cout << "订单ID: " << orderId << endl;
        cout << "订单类型: " << (orderType == "NORMAL" ? "普通订单" : "预售订单") << endl;
        cout << "用户ID: " << user.userId << endl;
        cout << "商品列表: ";
        for (auto& item : items) {
            cout << item.productId << "(" << item.price << "元) ";
        }
        cout << endl;

        if (coupon && !coupon->couponId.empty()) {
            cout << "优惠券: " << coupon->couponId << "(" << coupon->discount << "折)" << endl;
        } else {
            cout << "未使用优惠券" << endl;
        }

        if (logistics && !logistics->logisticsId.empty()) {
            cout << "物流信息: " << logistics->company << " " << logistics->logisticsId << endl;
        } else {
            cout << "未发货" << endl;
        }
    }

    // 析构函数释放动态内存
    ~Order() {
        delete coupon;
        delete logistics;
    }
};

// 抽象建造者:定义订单构建步骤,持有订单ID
class OrderBuilder {
protected:
    Order* order;      // 待构建的订单
    string orderId;    // 数据库主键:订单ID

public:
    // 构造函数接收订单ID
    OrderBuilder(string id) : orderId(id) {}
    virtual ~OrderBuilder() { delete order; }
    virtual void buildBasicInfo() = 0;  // 构建必选基础信息
    virtual void buildCoupon() = 0;     // 构建优惠券
    virtual void buildLogistics() = 0;  // 构建物流
    virtual Order* getResult() { return order; }
};

// 具体建造者1:普通订单建造者
class NormalOrderBuilder : public OrderBuilder {
public:
    NormalOrderBuilder(string id) : OrderBuilder(id) {}

    void buildBasicInfo() override {
        // 从数据库查询基础信息
        string userId = OrderDAO::getUserIdByOrderId(orderId);
        User user(userId);
        
        vector<pair<string, double>> productData = OrderDAO::getProductsByOrderId(orderId);
        vector<Product> items;
        for (auto& p : productData) {
            items.emplace_back(p.first, p.second);
        }
        
        order = new Order(orderId, "NORMAL", user, items);
    }

    void buildCoupon() override {
        // 从数据库查询优惠券
        auto couponData = OrderDAO::getCouponByOrderId(orderId);
        if (!couponData.first.empty()) {
            order->setCoupon(new Coupon(couponData.first, couponData.second));
        }
    }

    void buildLogistics() override {
        // 从数据库查询物流信息
        auto logisticsData = OrderDAO::getLogisticsByOrderId(orderId);
        if (!logisticsData.first.empty()) {
            order->setLogistics(new Logistics(logisticsData.first, logisticsData.second));
        }
    }
};

// 具体建造者2:预售订单建造者
class PresaleOrderBuilder : public OrderBuilder {
public:
    PresaleOrderBuilder(string id) : OrderBuilder(id) {}

    void buildBasicInfo() override {
        // 从数据库查询基础信息
        string userId = OrderDAO::getUserIdByOrderId(orderId);
        User user(userId);
        
        vector<pair<string, double>> productData = OrderDAO::getProductsByOrderId(orderId);
        vector<Product> items;
        for (auto& p : productData) {
            items.emplace_back(p.first, p.second);
        }
        
        order = new Order(orderId, "PRESALE", user, items);
        cout << "[预售订单] 已锁定库存" << endl;
    }

    void buildCoupon() override {
        // 从数据库查询预售专属优惠券
        auto couponData = OrderDAO::getCouponByOrderId(orderId);
        order->setCoupon(new Coupon(couponData.first, couponData.second));
    }

    void buildLogistics() override {
        // 从数据库查询物流信息(预售订单通常未发货)
        auto logisticsData = OrderDAO::getLogisticsByOrderId(orderId);
        if (!logisticsData.first.empty()) {
            order->setLogistics(new Logistics(logisticsData.first, logisticsData.second));
        } else {
            cout << "[预售订单] 待发货(预计7天后发货)" << endl;
        }
    }
};

// 建造者工厂:根据订单ID创建对应类型的建造者
class OrderBuilderFactory {
public:
    static OrderBuilder* createBuilder(const string& orderId) {
        // 先查询订单类型
        string orderType = OrderDAO::getOrderType(orderId);
        
        // 根据类型创建对应建造者
        if (orderType == "NORMAL") {
            return new NormalOrderBuilder(orderId);
        } else if (orderType == "PRESALE") {
            return new PresaleOrderBuilder(orderId);
        } else {
            throw invalid_argument("未知订单类型");
        }
    }
};

// 指挥者:控制订单构建流程
class OrderDirector {
public:
    Order* construct(OrderBuilder* builder) {
        builder->buildBasicInfo();   // 第一步:构建必选信息
        builder->buildCoupon();      // 第二步:处理优惠券
        builder->buildLogistics();   // 第三步:处理物流
        return builder->getResult();
    }
};

// 客户端使用
int main() {
    srand(time(0));
    OrderDirector director;

    // 1. 查询普通订单(已知订单ID)
    cout << "=== 查询普通订单 ===" << endl;
    string normalOrderId = "NORMAL_10086";
    OrderBuilder* normalBuilder = OrderBuilderFactory::createBuilder(normalOrderId);
    Order* normalOrder = director.construct(normalBuilder);
    normalOrder->show();

    // 2. 查询预售订单(已知订单ID)
    cout << "\n=== 查询预售订单 ===" << endl;
    string presaleOrderId = "PRESALE_10010";
    OrderBuilder* presaleBuilder = OrderBuilderFactory::createBuilder(presaleOrderId);
    Order* presaleOrder = director.construct(presaleBuilder);
    presaleOrder->show();

    return 0;
}
  • 产品:包含必选属性(订单 ID、用户、商品列表)和可选属性(优惠券、物流),是最终要创建的复杂对象。
  • 抽象建造者:定义订单构建的统一步骤(buildBasicInfobuildCouponbuildLogistics),并持有订单 ID 作为查询依据。
  • 具体建造者
    • NormalOrderBuilder:实现普通订单的数据库驱动构建逻辑,从OrderDAO获取用户、商品,随机应用优惠券,自动关联物流信息。
    • PresaleOrderBuilder:实现预售订单的特殊逻辑,从OrderDAO获取专属数据,包含库存锁定、强制使用预售优惠券、延迟发货提示等特有操作。
  • 建造者工厂:根据订单 ID 自动判断订单类型并创建对应建造者:通过OrderDAO.getOrderType查询类型,屏蔽客户端对订单类型的判断逻辑,简化调用流程。

  • 指挥者:控制建造流程的执行顺序,确保必选信息先于可选信息构建:隔离客户端与具体构建细节,无论哪种订单类型,均按固定步骤完成构建。

 运行效果示例

=== 查询普通订单 ===
订单ID: NORMAL_10086
订单类型: 普通订单
用户ID: user_001
商品列表: prod_001(99.9元) prod_002(199.9元) 
优惠券: coupon_001(9折)
物流信息: 顺丰快递 logi_001

=== 查询预售订单 ===
[预售订单] 已锁定库存
[预售订单] 待发货(预计7天后发货)
订单ID: PRESALE_10010
订单类型: 预售订单
用户ID: user_002
商品列表: prod_003(2999元) 
优惠券: presale_coupon_001(8.5折)
未发货

建造者模式的优势体现:

  • 解决参数爆炸:无需通过构造函数传递大量参数,建造者通过数据库查询自动填充信息。
  • 确保对象完整:指挥者强制必选信息优先构建,避免无效订单。
  • 隔离变化点:普通 / 预售订单的差异逻辑封装在各自建造者中,修改时互不干扰。
  • 支持灵活扩展:新增订单类型(如团购订单)时,只需新增GroupBuyOrderBuilder和工厂判断逻辑,完全符合开闭原则。

🦜🦜🦜.