设计模式分三大类:创建型(对象怎么造)、行为型(对象怎么交互)、结构型(对象怎么组合)。下面逐个讲原理、适用场景、C++ 完整可运行代码、优缺点。

一、单例模式(Singleton)—— 创建型

1. 核心思想

保证一个类全局只有唯一实例,提供全局访问点。

2. 使用场景

  • 全局配置管理器、日志工具、数据库连接池、窗口管理器
  • 资源昂贵,不能重复创建的对象

3. 两种实现:懒汉、饿汉

(1)饿汉单例(线程安全,程序启动直接创建)
#include <iostream>
using namespace std;

class Singleton {
private:
    // 1. 私有构造,禁止外部new
    Singleton() { cout << "创建单例实例" << endl; }
    // 禁止拷贝、赋值
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;

    // 2. 静态全局唯一实例(程序加载时初始化)
    static Singleton instance;

public:
    // 3. 全局获取接口
    static Singleton& getInstance() {
        return instance;
    }

    void log(string msg) {
        cout << "日志输出:" << msg << endl;
    }
};
// 类外初始化静态实例
Singleton Singleton::instance;

int main() {
    Singleton& s1 = Singleton::getInstance();
    Singleton& s2 = Singleton::getInstance();
    cout << &s1 << endl << &s2 << endl; // 地址完全相同
    s1.log("测试单例");
    return 0;
}

优点:天然线程安全,实现简单;缺点:程序启动就占用资源,不用也会创建。

(2)懒汉单例(用时才创建,C++11 静态局部变量线程安全)
class SingletonLazy {
private:
    Singleton() = default;
    SingletonLazy(const SingletonLazy&) = delete;
    SingletonLazy& operator=(const SingletonLazy&) = delete;
public:
    static SingletonLazy& getInstance() {
        // C++11规定:静态局部变量初始化线程安全
        static SingletonLazy ins;
        return ins;
    }
};

优点:延迟加载,节省资源;推荐项目使用。

4. 优缺点

  • 优点:全局唯一,统一管控资源,减少内存开销
  • 缺点:违背单一职责、难以单元测试、生命周期依赖程序进程

二、工厂模式(Factory)—— 创建型(简单工厂 + 工厂方法)

工厂模式核心依赖多态实现,没有多态就没有工厂模式的扩展性。

最通俗比喻

生活里的工厂:你想要一支笔,不用自己挖矿、提炼塑料、打磨笔尖、组装。直接去文具工厂下单,工厂帮你全部造好,你只管拿成品用。

代码里的工厂模式同理:创建对象(new XXX)的逻辑很复杂、种类很多,不交给使用者自己 new,统一交给专门的 “工厂类” 去创建对象。使用者只需要告诉工厂 “我要什么产品”,工厂返回成品,使用者不用关心创建细节。

分两层:简单工厂(静态工厂)工厂方法模式

1. 简单工厂(静态工厂)

核心

一个工厂类,根据参数动态生产不同产品

场景

同类产品多分支,创建逻辑集中管理。

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

// 产品基类
class Product {
public:
    virtual void show() = 0;
    virtual ~Product() = default;
};

// 产品A
class ProductA : public Product {
public:
    void show() override { cout << "产品A" << endl; }
};
// 产品B
class ProductB : public Product {
public:
    void show() override { cout << "产品B" << endl; }
};

// 简单工厂
class SimpleFactory {
public:
    static Product* createProduct(string type) {
        if (type == "A") return new ProductA();
        if (type == "B") return new ProductB();
        return nullptr;
    }
};

int main() {
    Product* p = SimpleFactory::createProduct("A");
    p->show();
    delete p;
    return 0;
}

缺点:新增产品必须修改工厂if-else,违反开闭原则

2. 工厂方法模式(优化版,符合开闭)

核心

一个产品对应一个工厂,基类定义工厂接口,新增产品只加工厂类,不改旧代码。

// 产品基类同上 Product
// 工厂基类
class Factory {
public:
    virtual Product* create() = 0;
    virtual ~Factory() = default;
};

// A工厂
class FactoryA : public Factory {
public:
    Product* create() override { return new ProductA(); }
};
// B工厂
class FactoryB : public Factory {
public:
    Product* create() override { return new ProductB(); }
};

int main() {
    Factory* f = new FactoryA();
    Product* p = f->create();
    p->show();
    delete p;
    delete f;
    return 0;
}

适用:产品会持续扩展,需要严格遵守开闭原则。

工厂模式总结

  • 作用:隔离对象创建逻辑,使用者只关心产品,不关心 new 细节
  • 简单工厂:快速开发,产品少;工厂方法:易扩展,产品多

三、策略模式(Strategy)—— 行为型

1. 核心思想

把一堆可以互相替换的算法 / 业务逻辑,各自封装成独立类,运行时随便切换,消灭代码里成堆的 if-else /switch。 

2. 场景

  • 支付方式(微信 / 支付宝 / 银行卡)、排序算法、折扣计算、文件解析器

3. C++ 代码示例:支付策略

#include <iostream>
using namespace std;

// 策略基类:支付算法
class PayStrategy {
public:
    virtual void pay(int money) = 0;
    virtual ~PayStrategy() = default;
};

// 微信支付策略
class WechatPay : public PayStrategy {
public:
    void pay(int money) override {
        cout << "微信支付:" << money << "元" << endl;
    }
};
// 支付宝策略
class AliPay : public PayStrategy {
public:
    void pay(int money) override {
        cout << "支付宝支付:" << money << "元" << endl;
    }
};

// 上下文Context:持有策略,对外统一接口
class Order {
private:
    PayStrategy* strategy;
public:
    // 动态设置策略
    void setStrategy(PayStrategy* s) {
        strategy = s;
    }
    void checkout(int total) {
        strategy->pay(total);
    }
};

int main() {
    Order order;
    PayStrategy* wechat = new WechatPay();
    PayStrategy* ali = new AliPay();

    order.setStrategy(wechat);
    order.checkout(100);

    // 运行时切换策略
    order.setStrategy(ali);
    order.checkout(200);

    delete wechat;
    delete ali;
    return 0;
}

优缺点

  • 优点:消灭臃肿 if-else,算法独立可单元测试,动态切换,符合开闭
  • 缺点:策略类数量膨胀,客户端需要知道所有策略才能切换

四、状态模式(State)—— 行为型

1. 核心思想

对象的行为依赖自身状态,不同状态执行完全不同逻辑;把每个状态封装为独立类,状态切换自动流转。

和策略模式区分:策略:算法平行互换,外部主动切换;状态:状态内部自动流转,上下文随条件自动换状态。

2. 场景

电梯运行(开门 / 关门 / 上行 / 下行)、订单状态(待支付 / 已支付 / 已发货 / 完成)、游戏角色状态

3. 示例:电梯状态机

#include <iostream>
using namespace std;

// 前置声明上下文
class Elevator;

// 状态基类
class State {
protected:
    Elevator* ctx;
public:
    State(Elevator* e) : ctx(e) {}
    virtual void open() = 0;
    virtual void close() = 0;
    virtual void run() = 0;
    virtual ~State() = default;
};

// 上下文:电梯
class Elevator {
public:
    State* curState;
    void setState(State* s) { curState = s; }
    void openDoor() { curState->open(); }
    void closeDoor() { curState->close(); }
    void runLift() { curState->run(); }
};

// 开门状态
class OpenState : public State {
public:
    using State::State;
    void open() override { cout << "门已经开着" << endl; }
    void close() override;
    void run() override { cout << "开门不能运行电梯" << endl; }
};

// 关门状态
class CloseState : public State {
public:
    using State::State;
    void open() override { cout << "开门" << endl; ctx->setState(new OpenState(ctx)); }
    void close() override { cout << "门已关闭" << endl; }
    void run() override { cout << "电梯启动运行" << endl; }
};

void OpenState::close() {
    cout << "关门" << endl;
    ctx->setState(new CloseState(ctx));
}

int main() {
    Elevator lift;
    lift.setState(new CloseState(&lift));
    lift.openDoor();  // 切换开门状态
    lift.runLift();   // 开门禁止运行
    lift.closeDoor(); // 切回关门
    lift.runLift();
    return 0;
}

优缺点

  • 优点:状态逻辑拆分,消除大量状态判断 if/switch,状态流转清晰
  • 缺点:状态类数量多,状态切换管理复杂

五、观察者模式(Observer)—— 行为型,发布订阅

1. 核心思想

一对多依赖:主题(发布者)状态变化时,自动通知所有订阅观察者,解耦发布与接收。

2. 场景

GUI 事件监听、消息推送、日志订阅、游戏事件、MQ 简易实现

3. C++ 代码

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

// 观察者基类
class Observer {
public:
    virtual void update(string msg) = 0;
    virtual ~Observer() = default;
};

// 主题(发布者)
class Subject {
private:
    vector<Observer*> obsList;
public:
    // 订阅
    void attach(Observer* o) { obsList.push_back(o); }
    // 取消订阅
    void detach(Observer* o) {
        for (auto it = obsList.begin(); it != obsList.end();) {
            if (*it == o) it = obsList.erase(it);
            else ++it;
        }
    }
    // 广播通知所有观察者
    void notify(string msg) {
        for (auto o : obsList) o->update(msg);
    }
};

// 具体观察者:用户A
class UserA : public Observer {
public:
    void update(string msg) override {
        cout << "用户A收到消息:" << msg << endl;
    }
};
class UserB : public Observer {
public:
    void update(string msg) override {
        cout << "用户B收到消息:" << msg << endl;
    }
};

int main() {
    Subject news;
    UserA a; UserB b;
    news.attach(&a);
    news.attach(&b);

    news.notify("今日热点:C++设计模式"); // 全部收到
    news.detach(&b);
    news.notify("第二条新闻"); // 只有A收到
    return 0;
}

优缺点

  • 优点:发布订阅完全解耦,一对多广播,动态增删观察者
  • 缺点:通知顺序不可控,大量观察者会有性能开销;循环依赖易内存泄漏


模式快速分类总结

表格

模式类型核心作用核心关键词
单例创建型全局唯一实例私有构造、静态实例
工厂创建型统一创建对象,隔离 new产品基类、工厂生产
策略行为型动态替换平行算法Context 持有策略,外部切换
状态行为型根据内部状态自动切换逻辑状态内部流转、状态机
观察者行为型一对多消息通知发布 - 订阅、广播更新

高频对比易混点

  1. 策略 vs 状态
    • 策略:算法平等互换,外部主动传入切换;无状态流转关系
    • 状态:对象自带状态,内部条件自动切换,有流转顺序
  2. 单例 vs 静态类
    • 单例是对象,可继承、传参、延迟创建;静态类全静态,无实例生命周期
Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐