(11)建造者模式

建造者模式核心思想,将一个复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示
业务场景:复杂对象构建 —— Web服务器配置生成器
你需要创建一个 WebServerConfig 对象,它包含多个可选配置项:
 - 监听端口
 - 根目录
 - 是否启用 HTTPS
 - SSL 证书路径
 - 日志级别
 - 最大连接数
 - Gzip 压缩
 - 自定义中间件

这个对象字段多、部分可选、构造过程复杂,直接使用构造函数会导致:
 - 参数爆炸(telescoping constructor)
 - 难以阅读和维护
 - 无法灵活组合
各类零散配置
#include <iostream>
#include <string>
#include <memory>
#include <vector>

using std::string;
using std::unique_ptr;
using std::vector;

// ==================== 日志级别枚举 ====================
enum class LogLevel {
    DEBUG,
    INFO,
    WARN,
    ERROR
};

string logLevelToString(LogLevel level) {
    switch (level) {
        case LogLevel::DEBUG: return "DEBUG";
        case LogLevel::INFO:  return "INFO";
        case LogLevel::WARN:  return "WARN";
        case LogLevel::ERROR: return "ERROR";
        default: return "UNKNOWN";
    }
}

// ==================== 中间件类(可插拔组件)====================
class Middleware {
protected:
    string name;
public:
    Middleware(const string& n) : name(n) {}
    virtual ~Middleware() = default;
    virtual void handle() const = 0;
    string getName() const { return name; }
};

class AuthMiddleware : public Middleware {
public:
    AuthMiddleware() : Middleware("认证中间件") {}
    void handle() const override {
        std::cout << "🔐 执行身份验证\n";
    }
};

class LoggingMiddleware : public Middleware {
public:
    LoggingMiddleware() : Middleware("日志中间件") {}
    void handle() const override {
        std::cout << "📝 记录访问日志\n";
    }
};
组合成最终配置类
// ==================== 最终产品:Web服务器配置 ====================
class WebServerConfig {
private:
    int port;
    string rootDir;
    bool enableHttps;
    string certFile;
    string keyFile;
    LogLevel logLevel;
    int maxConnections;
    bool enableGzip;
    vector<unique_ptr<Middleware>> middlewares;

    // 私有构造,只能由 Builder 创建
    WebServerConfig() = default;

    friend class WebServerConfigBuilder; // 允许 Builder 访问私有成员

public:
    // 禁止拷贝,允许移动
    WebServerConfig(const WebServerConfig&) = delete;
    WebServerConfig& operator=(const WebServerConfig&) = delete;

    WebServerConfig(WebServerConfig&&) = default;
    WebServerConfig& operator=(WebServerConfig&&) = default;

    ~WebServerConfig() = default;

    // 打印配置(用于调试)
    void print() const {
        std::cout << "\n🚀 Web服务器配置:\n";
        std::cout << "  端口: " << port << "\n";
        std::cout << "  根目录: " << rootDir << "\n";
        std::cout << "  HTTPS: " << (enableHttps ? "启用" : "禁用") << "\n";
        if (enableHttps) {
            std::cout << "  证书: " << certFile << "\n";
            std::cout << "  私钥: " << keyFile << "\n";
        }
        std::cout << "  日志级别: " << logLevelToString(logLevel) << "\n";
        std::cout << "  最大连接数: " << maxConnections << "\n";
        std::cout << "  Gzip压缩: " << (enableGzip ? "启用" : "禁用") << "\n";
        
        std::cout << "  中间件: ";
        if (middlewares.empty()) {
            std::cout << "无\n";
        } else {
            for (size_t i = 0; i < middlewares.size(); ++i) {
                std::cout << middlewares[i]->getName();
                if (i < middlewares.size() - 1) std::cout << ", ";
            }
            std::cout << "\n";
        }
        std::cout << "\n";
    }

    // 提供只读访问(可选)
    int getPort() const { return port; }
    const string& getRootDir() const { return rootDir; }
    bool isHttpsEnabled() const { return enableHttps; }
};
建造者类:WebServerConfigBuilder
class WebServerConfigBuilder {
private:
    unique_ptr<WebServerConfig> config;

public:
    WebServerConfigBuilder() {
        config = std::make_unique<WebServerConfig>();
        // 设置默认值
        config->port = 8080;
        config->rootDir = "./public";
        config->enableHttps = false;
        config->logLevel = LogLevel::INFO;
        config->maxConnections = 1000;
        config->enableGzip = false;
    }

    // 链式调用:设置端口
    WebServerConfigBuilder& setPort(int p) {
        if (p <= 0 || p > 65535) {
            throw std::invalid_argument("端口必须在 1-65535 之间");
        }
        config->port = p;
        return *this;
    }

    // 设置根目录
    WebServerConfigBuilder& setRootDir(const string& dir) {
        config->rootDir = dir;
        return *this;
    }

    // 启用 HTTPS
    WebServerConfigBuilder& enableHTTPS(const string& cert, const string& key) {
        config->enableHttps = true;
        config->certFile = cert;
        config->keyFile = key;
        return *this;
    }

    // 设置日志级别
    WebServerConfigBuilder& setLogLevel(LogLevel level) {
        config->logLevel = level;
        return *this;
    }

    // 设置最大连接数
    WebServerConfigBuilder& setMaxConnections(int maxConn) {
        if (maxConn <= 0) {
            throw std::invalid_argument("最大连接数必须大于0");
        }
        config->maxConnections = maxConn;
        return *this;
    }

    // 启用 Gzip
    WebServerConfigBuilder& enableGzip(bool on = true) {
        config->enableGzip = on;
        return *this;
    }

    // 添加中间件
    WebServerConfigBuilder& addMiddleware(unique_ptr<Middleware> middleware) {
        config->middlewares.push_back(std::move(middleware));
        return *this;
    }

    // 构建最终对象(移动语义)
    unique_ptr<WebServerConfig> build() {
        // 可选:构建前验证
        if (config->rootDir.empty()) {
            throw std::runtime_error("根目录不能为空");
        }

        return std::move(config); // 转移所有权
    }
};
创建不同配置的服务器
int main() {
    std::cout << "欢迎使用 Web 服务器配置生成器\n\n";

    // 场景1:开发环境配置
    auto devConfig = WebServerConfigBuilder{}
        .setPort(3000)
        .setRootDir("./dev-public")
        .setLogLevel(LogLevel::DEBUG)
        .enableGzip()
        .addMiddleware(std::make_unique<LoggingMiddleware>())
        .build();

    devConfig->print();

    // 场景2:生产环境配置(HTTPS + 认证)
    auto prodConfig = WebServerConfigBuilder{}
        .setPort(443)
        .setRootDir("/var/www/html")
        .enableHTTPS("/certs/server.crt", "/certs/server.key")
        .setMaxConnections(5000)
        .enableGzip()
        .addMiddleware(std::make_unique<AuthMiddleware>())
        .addMiddleware(std::make_unique<LoggingMiddleware>())
        .build();

    prodConfig->print();

    // 场景3:最小化配置(嵌入式设备)
    auto tinyConfig = WebServerConfigBuilder{}
        .setPort(80)
        .setRootDir("./web")
        .setLogLevel(LogLevel::ERROR)
        .setMaxConnections(50)
        .build();

    tinyConfig->print();

    return 0;
}
使用模板优化
#include <iostream>
#include <string>
#include <memory>
#include <vector>

using std::string;
using std::unique_ptr;
using std::vector;

// ================ 1. 中间件基类(用于扩展功能) ====================
// 所有中间件都继承自这个类
struct Middleware {
    virtual ~Middleware() = default;
    virtual void handle() const = 0;
    virtual std::string getName() const = 0;
};

// 认证中间件示例
struct AuthMiddleware : Middleware {
    void handle() const override { std::cout << "执行身份验证\n"; }
    std::string getName() const override { return "认证中间件"; }
};

// 日志中间件示例
struct LoggingMiddleware : Middleware {
    void handle() const override { std::cout << "记录访问日志\n"; }
    std::string getName() const override { return "日志中间件"; }
};
// ============= 2. 策略配置类(每个配置项一个策略) ================
// 端口配置策略
struct PortPolicy {
    int port = 8080; // 默认端口

    // 设置端口并返回建造者自身(用于链式调用)
    template<typename Builder>
    Builder& setPort(Builder& builder, int p) {
        builder.port = p;
        return builder;
    }
};

// 根目录策略
struct RootDirPolicy {
    string rootDir = "./public"; // 默认路径

    template<typename Builder>
    Builder& setRootDir(Builder& builder, const string& dir) {
        builder.rootDir = dir;
        return builder;
    }
};

// HTTPS 策略
struct HttpsPolicy {
    bool enableHttps = false;
    string certFile;
    string keyFile;

    // 模板builder类
    template<typename Builder>
    Builder& enableHTTPS(Builder& builder, const string& cert, const string& key) {
        builder.enableHttps = true;
        builder.certFile = cert;
        builder.keyFile = key;
        return builder;
    }
};

// 日志级别策略
struct LogPolicy {
    enum class LogLevel { DEBUG, INFO, WARN, ERROR };
    LogLevel logLevel = LogLevel::INFO;
    
    // 模板builder类
    template<typename Builder>
    Builder& setLogLevel(Builder& builder, LogLevel level) {
        builder.logLevel = level;
        return builder;
    }
};

// 最大连接数策略
struct ConnectionPolicy {
    int maxConnections = 1000;

    // 模板builder类
    template<typename Builder>
    Builder& setMaxConnections(Builder& builder, int maxConn) {
        builder.maxConnections = maxConn;
        return builder;
    }
};

// Gzip 压缩策略
struct GzipPolicy {
    bool enableGzip = false;
 
    // 模板builder类
    template<typename Builder>
    Builder& enableGzip(Builder& builder, bool on = true) {
        builder.enableGzip = on;
        return builder;
    }
};

// 中间件列表策略
struct MiddlewarePolicy {
    vector<unique_ptr<Middleware>> middlewares;

    template<typename T>
    struct is_middleware : std::is_base_of<Middleware, T> {};

    template<typename Builder, typename T>
    std::enable_if_t<is_middleware<T>::value, Builder&>
    addMiddleware(Builder& builder) {
        builder.middlewares.push_back(std::make_unique<T>());
        return builder;
    }
};
模板建造者类
// ==================== 3. 模板建造者(核心) ====================
// 使用模板参数接收多个策略,组合成最终的建造者
template<typename... Policies>
class WebServerBuilder : public Policies... {
public:
    // 构造函数
    WebServerBuilder() = default;

    // 继承所有策略中的方法(C++17 支持 using...)
    using Policies::setPort...;
    using Policies::setRootDir...;
    using Policies::enableHTTPS...;
    using Policies::setLogLevel...;
    using Policies::setMaxConnections...;
    using Policies::enableGzip...;
    using Policies::addMiddleware...;

    // 最终配置结构体
    struct Config {
        int port;
        string rootDir;
        bool enableHttps;
        string certFile, keyFile;
        LogPolicy::LogLevel logLevel;
        int maxConnections;
        bool enableGzip;
        vector<unique_ptr<Middleware>> middlewares;

        // 打印配置信息
        void print() const {
            std::cout << "\n🚀 Web服务器配置:\n";
            std::cout << "  端口: " << port << "\n";
            std::cout << "  根目录: " << rootDir << "\n";
            std::cout << "  HTTPS: " << (enableHttps ? "启用" : "禁用") << "\n";
            if (enableHttps) {
                std::cout << "  证书: " << certFile << "\n";
                std::cout << "  私钥: " << keyFile << "\n";
            }
            std::cout << "  日志级别: ";
            switch (logLevel) {
                case LogPolicy::LogLevel::DEBUG: std::cout << "DEBUG"; break;
                case LogPolicy::LogLevel::INFO:  std::cout << "INFO";  break;
                case LogPolicy::LogLevel::WARN:  std::cout << "WARN";  break;
                case LogPolicy::LogLevel::ERROR: std::cout << "ERROR"; break;
            }
            std::cout << "\n";
            std::cout << "  最大连接数: " << maxConnections << "\n";
            std::cout << "  Gzip压缩: " << (enableGzip ? "启用" : "禁用") << "\n";

            std::cout << "  中间件: ";
            if (middlewares.empty()) {
                std::cout << "无\n";
            } else {
                for (size_t i = 0; i < middlewares.size(); ++i) {
                    std::cout << middlewares[i]->getName();
                    if (i < middlewares.size() - 1) std::cout << ", ";
                }
                std::cout << "\n";
            }
            std::cout << "\n";
        }
    };

    // 构建最终的配置对象
    unique_ptr<Config> build() {
        auto config = std::make_unique<Config>();
        config->port = port;
        config->rootDir = rootDir;
        config->enableHttps = enableHttps;
        config->certFile = certFile;
        config->keyFile = keyFile;
        config->logLevel = logLevel;
        config->maxConnections = maxConnections;
        config->enableGzip = enableGzip;
        config->middlewares = std::move(middlewares); // 转移所有权
        return config;
    }
};

// ============ 4. 定义不同类型的建造者(类型别名) ================
// 开发环境:不需要 HTTPS,但需要日志和 Gzip
using DevBuilder = WebServerBuilder<
    PortPolicy,
    RootDirPolicy,
    LogPolicy,
    GzipPolicy,
    MiddlewarePolicy
>;

// 生产环境:需要 HTTPS、连接数限制等
using ProdBuilder = WebServerBuilder<
    PortPolicy,
    RootDirPolicy,
    HttpsPolicy,
    LogPolicy,
    ConnectionPolicy,
    GzipPolicy,
    MiddlewarePolicy
>;
// ==================== 5. 使用示例 ====================
int main() {
    std::cout << "欢迎使用简化版 C++17 建造者模式\n\n";

    // 创建开发环境配置
    auto devConfig = DevBuilder{}
        .setPort(3000)
        .setRootDir("./dev-public")
        .setLogLevel(LogPolicy::LogLevel::DEBUG)
        .enableGzip()
        .addMiddleware<LoggingMiddleware>()
        .build(); // 构建最终对象

    devConfig->print();

    // 创建生产环境配置
    auto prodConfig = ProdBuilder{}
        .setPort(443)
        .setRootDir("/var/www/html")
        .enableHTTPS("/certs/prod.crt", "/certs/prod.key")
        .setMaxConnections(5000)
        .setLogLevel(LogPolicy::LogLevel::INFO)
        .enableGzip()
        .addMiddleware<AuthMiddleware>()
        .addMiddleware<LoggingMiddleware>()
        .build();

    prodConfig->print();

    return 0;
}
posted @ 2018-12-13 22:20  osbreak  阅读(158)  评论(0)    收藏  举报