引言
在前面的文章中,我们学习了 C++ 语法、STL、数据结构。这些都是"怎么写代码"的工具。而设计模式解决的是更高层次的问题------"代码怎么组织才更好"。
设计模式是前辈们总结的、经过反复验证的代码组织方案。它不是凭空发明的,而是在无数项目中"踩坑"后提炼出的最佳实践。掌握设计模式,能让你写出更易维护、更易扩展、更易复用的代码。
本文聚焦 C++ 中最常用的四种设计模式:单例模式 、工厂模式 、观察者模式 和策略模式。

第一部分:单例模式
一、什么是单例模式
保证一个类只有一个实例,并提供全局访问点。比如程序的配置管理器、日志系统、数据库连接池------这些东西整个程序只需要一份。

二、懒汉式(用到才创建)
cpp
#include <iostream>
#include <mutex>
using namespace std;
class Singleton {
private:
static Singleton* instance;
static mutex mtx;
// 构造函数私有!外部不能 new
Singleton() { cout << "单例创建" << endl; }
// 禁止拷贝和赋值
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
public:
// 全局访问点(线程安全)
static Singleton* getInstance() {
if (instance == nullptr) {
lock_guard<mutex> lock(mtx); // 加锁
if (instance == nullptr) { // 双重检查
instance = new Singleton();
}
}
return instance;
}
void doSomething() { cout << "工作" << endl; }
};
// 静态成员初始化
Singleton* Singleton::instance = nullptr;
mutex Singleton::mtx;
int main() {
Singleton* s1 = Singleton::getInstance();
Singleton* s2 = Singleton::getInstance();
cout << (s1 == s2) << endl; // 1(同一个对象)
// Singleton s3; // 错误!构造私有
}
为什么用双重检查锁?

三、C++11 最简写法(推荐)
C++11 保证了静态局部变量的线程安全,一行搞定:
cpp
class Singleton {
private:
Singleton() = default;
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
public:
static Singleton& getInstance() {
static Singleton instance; // C++11 保证线程安全!
return instance;
}
};
第二部分:工厂模式
一、简单工厂
把对象的创建逻辑集中到一个工厂类中,调用者不需要知道具体怎么创建。
cpp
#include <iostream>
#include <string>
using namespace std;
// 产品基类
class Animal {
public:
virtual void speak() = 0;
virtual ~Animal() = default;
};
// 具体产品
class Dog : public Animal {
public:
void speak() override { cout << "汪汪" << endl; }
};
class Cat : public Animal {
public:
void speak() override { cout << "喵喵" << endl; }
};
// 简单工厂
class AnimalFactory {
public:
static Animal* createAnimal(const string& type) {
if (type == "dog") return new Dog();
if (type == "cat") return new Cat();
return nullptr;
}
};
int main() {
Animal* dog = AnimalFactory::createAnimal("dog");
dog->speak(); // 汪汪
Animal* cat = AnimalFactory::createAnimal("cat");
cat->speak(); // 喵喵
delete dog;
delete cat;
}
二、工厂方法模式
每个具体产品对应一个具体工厂,新增产品时不修改已有代码(开闭原则)。
cpp
// 抽象工厂
class AnimalFactory {
public:
virtual Animal* createAnimal() = 0;
virtual ~AnimalFactory() = default;
};
// 具体工厂
class DogFactory : public AnimalFactory {
public:
Animal* createAnimal() override { return new Dog(); }
};
class CatFactory : public AnimalFactory {
public:
Animal* createAnimal() override { return new Cat(); }
};
int main() {
DogFactory dogFactory;
Animal* dog = dogFactory.createAnimal();
dog->speak(); // 汪汪
CatFactory catFactory;
Animal* cat = catFactory.createAnimal();
cat->speak(); // 喵喵
delete dog;
delete cat;
}
| 工厂类型 | 特点 | 适用场景 |
|---|---|---|
| 简单工厂 | 一个工厂创建所有产品 | 产品类型少,变化不频繁 |
| 工厂方法 | 每个产品对应一个工厂 | 产品类型多,经常新增 |
第三部分:观察者模式
定义一对多依赖关系,当被观察者状态变化时,自动通知所有观察者。比如 GUI 的事件监听、消息订阅通知。
cpp
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
// 观察者接口
class Observer {
public:
virtual void update(const string& message) = 0;
virtual ~Observer() = default;
};
// 被观察者
class Subject {
private:
vector<Observer*> observers;
string state;
public:
// 注册观察者
void attach(Observer* obs) {
observers.push_back(obs);
}
// 移除观察者
void detach(Observer* obs) {
observers.erase(
remove(observers.begin(), observers.end(), obs),
observers.end()
);
}
// 通知所有观察者
void notify() {
for (auto* obs : observers) {
obs->update(state);
}
}
// 改变状态并通知
void setState(const string& newState) {
state = newState;
notify(); // 状态一改变就通知
}
};
// 具体观察者
class User : public Observer {
private:
string name;
public:
User(const string& name) : name(name) {}
void update(const string& message) override {
cout << name << " 收到通知:" << message << endl;
}
};
int main() {
Subject subject;
User alice("Alice");
User bob("Bob");
subject.attach(&alice);
subject.attach(&bob);
subject.setState("新版本发布了!");
// Alice 收到通知:新版本发布了!
// Bob 收到通知:新版本发布了!
subject.detach(&bob);
subject.setState("服务器维护中...");
// Alice 收到通知:服务器维护中...
// (Bob 已取消订阅,不会收到)
}
第四部分:策略模式
定义一系列算法,把它们封装起来,让它们可以互相替换。比如排序可以选快排、归并;支付可以选微信、支付宝。
cpp
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// 策略接口
class SortStrategy {
public:
virtual void sort(vector<int>& data) = 0;
virtual ~SortStrategy() = default;
};
// 具体策略:升序
class AscendingSort : public SortStrategy {
public:
void sort(vector<int>& data) override {
std::sort(data.begin(), data.end());
}
};
// 具体策略:降序
class DescendingSort : public SortStrategy {
public:
void sort(vector<int>& data) override {
std::sort(data.begin(), data.end(), greater<int>());
}
};
// 使用策略的类
class DataProcessor {
private:
SortStrategy* strategy;
public:
void setStrategy(SortStrategy* s) { strategy = s; }
void process(vector<int>& data) {
if (strategy) {
strategy->sort(data);
}
}
};
int main() {
vector<int> data = {5, 2, 8, 1, 9};
DataProcessor processor;
AscendingSort asc;
DescendingSort desc;
// 用升序策略
processor.setStrategy(&asc);
processor.process(data); // 1 2 5 8 9
// 切换到降序策略
processor.setStrategy(&desc);
processor.process(data); // 9 8 5 2 1
}
策略模式的核心 :用组合 代替继承,算法可以在运行时灵活切换,不需要改代码。
总结
一、四种模式速查
| 模式 | 核心思想 | 关键实现 |
|---|---|---|
| 单例 | 全局唯一实例 | 构造私有 + 静态 getInstance() |
| 工厂 | 把创建逻辑封装起来 | 工厂类返回产品指针 |
| 观察者 | 状态变化自动通知 | vector<Observer*> + notify() |
| 策略 | 算法可替换 | 策略接口 + setStrategy() |
二、一句话记忆
单例构造私有化保证全局唯一,工厂把创建和使用分离,观察者实现一对多自动通知,策略让算法可以随时替换------四大模式都是为了让代码更灵活、更好改、更好测。