一文学会设计模式之创建型模式及最佳实现

创建型设计模式(Creational Design Patterns)关注对象的创建机制,旨在在不指定具体类的情况下创建对象,提高系统的灵活性和可维护性。C++ 中常见的创建型模式有以下五种:


五种创建型模式对比表

模式 适用场景 C++ 推荐实现要点
单例 全局唯一资源管理 Magic Static + delete 拷贝
工厂方法 创建单一产品,延迟到子类 虚函数 + unique_ptr
抽象工厂 创建产品族 多产品接口 + 工厂聚合
建造者 复杂对象分步构建 Fluent interface / 链式调用
原型 高成本对象复制 clone() + 深拷贝语义

1. 单例模式(Singleton)

关键点

  • 确保一个类只有一个实例,并提供全局访问点。
  • 构造函数私有化,禁止外部直接构造。
  • 使用静态成员变量保存唯一实例。

优缺点

优点 缺点
节省内存,避免重复创建 全局状态,破坏封装性
提供全局访问点 难以测试(依赖全局状态)
控制资源(如日志、配置) 多线程需额外同步

C++ 最佳实现(C++11 起,线程安全)

cpp 复制代码
class Singleton {
public:
    static Singleton& getInstance() {
        static Singleton instance; // Magic Static,C++11 起线程安全
        return instance;
    }

    // 删除拷贝和赋值(C++11)
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;

private:
    Singleton() = default; // 私有构造
};

调用方式

cpp 复制代码
auto& s = Singleton::getInstance();

2. 工厂方法模式(Factory Method)

关键点

  • 定义创建对象的接口,但让子类决定实例化哪个类。
  • 将对象创建延迟到子类。

优缺点

优点 缺点
解耦客户端与具体产品 类数量增加
符合开闭原则(新增产品只需加子类) 每个产品需对应一个工厂子类

C++ 实现

cpp 复制代码
// 产品基类
class Product {
public:
    virtual ~Product() = default;
    virtual void use() = 0;
};

// 具体产品
class ConcreteProductA : public Product {
public:
    void use() override { std::cout << "Using A\n"; }
};

// 工厂基类
class Creator {
public:
    virtual ~Creator() = default;
    virtual std::unique_ptr<Product> createProduct() = 0;
};

// 具体工厂
class ConcreteCreatorA : public Creator {
public:
    std::unique_ptr<Product> createProduct() override {
        return std::make_unique<ConcreteProductA>();
    }
};

调用方式

cpp 复制代码
ConcreteCreatorA factory;
auto product = factory.createProduct();
product->use();

3. 抽象工厂模式(Abstract Factory)

关键点

  • 提供一个创建一系列相关或依赖对象的接口,而无需指定具体类。
  • 适用于产品族(多个相关产品组合)。

优缺点

优点 缺点
保证产品族的一致性 增加系统复杂度
易于切换产品族 难以支持新种类产品(违反开闭)

C++ 实现

cpp 复制代码
// 抽象产品 A 和 B
class AbstractProductA { public: virtual ~AbstractProductA() = default; };
class AbstractProductB { public: virtual ~AbstractProductB() = default; };

// 具体产品
class ProductA1 : public AbstractProductA {};
class ProductB1 : public AbstractProductB {};

// 抽象工厂
class AbstractFactory {
public:
    virtual ~AbstractFactory() = default;
    virtual std::unique_ptr<AbstractProductA> createProductA() = 0;
    virtual std::unique_ptr<AbstractProductB> createProductB() = 0;
};

// 具体工厂
class ConcreteFactory1 : public AbstractFactory {
public:
    std::unique_ptr<AbstractProductA> createProductA() override {
        return std::make_unique<ProductA1>();
    }
    std::unique_ptr<AbstractProductB> createProductB() override {
        return std::make_unique<ProductB1>();
    }
};

调用方式

cpp 复制代码
auto factory = std::make_unique<ConcreteFactory1>();
auto pA = factory->createProductA();
auto pB = factory->createProductB();

4. 建造者模式(Builder)

关键点

  • 将复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同表示。
  • 适用于对象由多个部分组成、且构造过程复杂。
  • c++中不可变对象推荐使用 "命名构造器" 或 "参数对象",而不是 Builder 模式,防止过度设计。

优缺点

优点 缺点
分离构造与表示 代码量大
可精细控制构建过程 仅适用于复杂对象

C++ 实现(现代 C++ 风格,使用 fluent interface)

cpp 复制代码
class Product {
public:
    void setPartA(int a) { partA_ = a; }
    void setPartB(std::string b) { partB_ = std::move(b); }
private:
    int partA_ = 0;
    std::string partB_;
};

class Builder {
public:
    virtual ~Builder() = default;
    virtual Builder& setPartA(int a) = 0;
    virtual Builder& setPartB(std::string b) = 0;
    virtual Product build() = 0;
};

class ConcreteBuilder : public Builder {
    Product product_;
public:
    Builder& setPartA(int a) override {
        product_.setPartA(a);
        return *this;
    }
    Builder& setPartB(std::string b) override {
        product_.setPartB(std::move(b));
        return *this;
    }
    Product build() override {
        return std::move(product_);
    }
};

调用方式(链式调用)

cpp 复制代码
ConcreteBuilder builder;
auto product = builder.setPartA(10).setPartB("hello").build();

5. 原型模式(Prototype)

关键点

  • 通过复制现有对象(原型)来创建新对象,而非通过 new。
  • 要求对象支持克隆(深拷贝)。

优缺点

优点 缺点
避免重复初始化开销 需要正确实现深拷贝
动态配置对象 循环引用等复杂结构难克隆

C++ 实现(使用 clone 虚函数)

cpp 复制代码
class Prototype {
public:
    virtual ~Prototype() = default;
    virtual std::unique_ptr<Prototype> clone() const = 0;
};

class ConcretePrototype : public Prototype {
    int value_;
    std::string data_;
public:
    ConcretePrototype(int v, std::string d) : value_(v), data_(std::move(d)) {}

    std::unique_ptr<Prototype> clone() const override {
        return std::make_unique<ConcretePrototype>(*this); // 调用拷贝构造
    }
};

调用方式

cpp 复制代码
ConcretePrototype proto(42, "example");
auto copy = proto.clone(); // 返回 unique_ptr<Prototype>
相关推荐
苦藤新鸡10 小时前
8.最长的无重复字符的子串
c++·力扣
꧁Q༒ོγ꧂11 小时前
C++ 入门完全指南(四)--函数与模块化编程
开发语言·c++
汉克老师11 小时前
GESP2025年12月认证C++八级真题与解析(判断题8-10)
c++·快速排序··lcs·gesp八级·gesp8级
qq_4335545411 小时前
C++ manacher(求解回文串问题)
开发语言·c++·算法
HL_风神12 小时前
设计原则之迪米特
c++·学习·设计模式
HL_风神12 小时前
设计原则之合成复用
c++·学习·设计模式
汉克老师13 小时前
GESP2025年12月认证C++八级真题与解析(单选题10-12)
c++·递归··gesp八级·gesp8级
bkspiderx13 小时前
C++中的map容器:键值对的有序管理与高效检索
开发语言·c++·stl·map
Hard but lovely14 小时前
Linux: 线程同步-- 基于条件变量 &&生产消费模型
linux·开发语言·c++
L_090714 小时前
【C++】高阶数据结构 -- 平衡二叉树(AVLTree)
数据结构·c++