news 2026/7/16 12:52:27

C++ 六大常用设计模式详解(单例、工厂、策略、状态、观察者、代理)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C++ 六大常用设计模式详解(单例、工厂、策略、状态、观察者、代理)

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

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

1. 核心思想

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

2. 使用场景

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

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

(1)饿汉单例(线程安全,程序启动直接创建)

cpp

#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 静态局部变量线程安全)

cpp

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)—— 创建型(简单工厂 + 工厂方法)

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

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

核心

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

场景

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

cpp

#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. 工厂方法模式(优化版,符合开闭)

核心

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

cpp

// 产品基类同上 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

2. 场景

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

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

cpp

#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. 示例:电梯状态机

cpp

#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++ 代码

cpp

#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; }

优缺点

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

六、代理模式(Proxy)—— 结构型

1. 核心思想

提供代理对象,控制对真实目标对象的访问;在调用真实对象前后加逻辑(缓存、鉴权、日志、延迟创建)。分类:静态代理、动态代理(C++ 无原生动态代理,一般用静态)

2. 使用场景

远程代理(RPC)、虚拟代理(大图片延迟加载)、保护代理(权限校验)、日志缓存代理

3. 静态代理完整示例(图片加载)

cpp

#include <iostream> #include <string> using namespace std; // 公共抽象接口 class Image { public: virtual void display() = 0; virtual ~Image() = default; }; // 真实对象:大图加载耗时 class RealImage : public Image { private: string path; public: RealImage(string p) : path(p) { cout << "加载大图资源:" << path << endl; } void display() override { cout << "展示图片:" << path << endl; } }; // 代理对象:虚拟代理,延迟加载 class ImageProxy : public Image { private: string path; RealImage* realImg = nullptr; public: ImageProxy(string p) : path(p) {} void display() override { // 延迟创建真实对象 if (!realImg) realImg = new RealImage(path); realImg->display(); } ~ImageProxy() { delete realImg; } }; int main() { // 创建代理,此时不加载大图 Image* img = new ImageProxy("big_pic.png"); cout << "页面渲染完成,点击才加载图片\n"; img->display(); // 第一次调用才加载 img->display(); // 第二次直接展示,无需重复加载 delete img; return 0; }

代理模式变种说明

  1. 虚拟代理:延迟创建重量级对象(上图示例)
  2. 保护代理:调用前校验权限,无权限禁止访问真实对象
  3. 日志代理:统一打印接口调用日志、耗时统计
  4. 远程代理:封装网络请求,隐藏跨进程 / 跨机器调用细节

优缺点

  • 优点:控制访问、扩展附加逻辑(缓存 / 鉴权 / 日志)、延迟加载、隔离真实对象
  • 缺点:多一层代理类,增加代码复杂度

模式快速分类总结

表格

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

高频对比易混点

  1. 策略 vs 状态
    • 策略:算法平等互换,外部主动传入切换;无状态流转关系
    • 状态:对象自带状态,内部条件自动切换,有流转顺序
  2. 工厂 vs 代理
    • 工厂:只管创建对象;代理:包装已有对象,控制访问
  3. 单例 vs 静态类
    • 单例是对象,可继承、传参、延迟创建;静态类全静态,无实例生命周期
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/16 12:52:10

yuzu模拟器完全指南:在PC上完美运行Switch游戏的终极解决方案

yuzu模拟器完全指南&#xff1a;在PC上完美运行Switch游戏的终极解决方案 【免费下载链接】yuzu 任天堂 Switch 模拟器 项目地址: https://gitcode.com/GitHub_Trending/yu/yuzu 你是否曾经梦想在PC上畅玩任天堂Switch的独占游戏&#xff1f;是否对Switch游戏的高昂价格…

作者头像 李华
网站建设 2026/7/16 12:50:54

DDE-GoCode核心组件深度解析:10个关键Golang包详解

DDE-GoCode核心组件深度解析&#xff1a;10个关键Golang包详解 【免费下载链接】DDE-GoCode dde desktop need some golang depend package 项目地址: https://gitcode.com/openeuler/DDE-GoCode 前往项目官网免费下载&#xff1a;https://ar.openeuler.org/ar/ DDE-Go…

作者头像 李华
网站建设 2026/7/16 12:49:10

Autolab终极指南:如何用自动化编程作业评分系统提升教学效率

Autolab终极指南&#xff1a;如何用自动化编程作业评分系统提升教学效率 【免费下载链接】Autolab Course management service that enables auto-graded programming assignments. 项目地址: https://gitcode.com/gh_mirrors/au/Autolab 还在为批改数百份编程作业而头疼…

作者头像 李华
网站建设 2026/7/16 12:48:08

CentOS 7下Tomcat 8.5生产环境部署与调优指南

1. CentOS 7环境下Tomcat 8.5生产级部署全指南在当今企业级Java应用部署中&#xff0c;Tomcat作为轻量级应用服务器占据着重要地位。根据Apache官方统计&#xff0c;Tomcat 8.5系列在稳定性和性能方面表现优异&#xff0c;至今仍是许多生产环境的首选版本。本文将基于CentOS 7操…

作者头像 李华