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

创建型设计模式(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>
相关推荐
️停云️2 小时前
C++类型转换、IO流与特殊类的设计
c语言·开发语言·c++
进击的荆棘2 小时前
C++起始之路——类和对象(下)
开发语言·c++
liu****3 小时前
10.排序
c语言·开发语言·数据结构·c++·算法·排序算法
快乐的划水a3 小时前
std::thread与pthread关系
c++
_OP_CHEN3 小时前
【算法基础篇】(三十二)动态规划之背包问题扩展:从多重到多维,解锁背包问题全场景
c++·算法·蓝桥杯·动态规划·背包问题·算法竞赛·acm/icpc
Studying 开龙wu3 小时前
Windos 10系统安装OpenPose的CPU版本过程说明和Release版本直接使用
c++·windows
温柔の敲代码4 小时前
从微观到宏观了解C++项目的编译
开发语言·c++
1024肥宅4 小时前
前端常用模式:提升代码质量的四大核心模式
前端·javascript·设计模式
另寻沧海4 小时前
C++ Lambda表达式的隐式转换陷阱
java·c++·算法