针对一些经典的常见的场景, 给定了一些对应的解决方案,这个就叫设计模式。
设计模式的作用:使代码的可重用性高,可读性强,灵活性好,可维护性强。
设计原则:
单一职责原则:一个类只做一方面的事。
开闭原则:以前写过的代码不能动,修改以前写的代码是非常危险的事情,我们可以在原来的基础上进行扩展,例如添加新的方法。
接口隔离原则:接口定义的功能尽量少,不要包含太多的功能。
里氏替换原则:在继承关系的代码开发中,如果需要进行功能的扩展,不要在子类中改变父类中已经实现的方法,而是通过新增方法来扩展父类的功能。
依赖倒置原则:在定义类的成员变量,参数类型,返回值类型的时候,不要写某个具体的实现类,而是尽量采用接口或者抽象类,这样后续如果我们想改,不需要改动代码,只需要增加实现类就可以了。
创建型模式:
创建型模式:用于解耦对象实例化的过程。
工厂模式:
工厂模式 的思想是将对象的创建逻辑封装到一个专门的类中 ,客户端无需直接 new
具体类,从而降低代码耦合。
当对象创建逻辑复杂,或需要统一管理创建过程时使用工厂模式。
cpp
#include <iostream>
// 抽象产品类(接口)
class Shape {
public:
virtual void draw() = 0;
virtual ~Shape() {} // 虚析构,确保正确释放子类对象
};
// 具体产品类:圆形
class Circle : public Shape {
public:
void draw() override {
std::cout << "Drawing a Circle" << std::endl;
}
};
// 具体产品类:方形
class Square : public Shape {
public:
void draw() override {
std::cout << "Drawing a Square" << std::endl;
}
};
简单工厂模式:
定义抽象产品类,具体产品类,工厂类,用户不必知道创建对象的细节,只需要调用工厂类(静态创建对象函数)。(针对单一产品)
违反了开闭原则,新增产品类需要修改工厂类的代码。
cpp
// 工厂类
class ShapeFactory {
public:
// 根据类型创建对象(静态方法)
static Shape* createShape(const std::string& type) {
if (type == "Circle") {
return new Circle();
} else if (type == "Square") {
return new Square();
}
return nullptr; // 无效类型返回空
}
};
// 客户端代码
int main() {
// 通过工厂创建对象
Shape* circle = ShapeFactory::createShape("Circle");
Shape* square = ShapeFactory::createShape("Square");
circle->draw(); // 输出: Drawing a Circle
square->draw(); // 输出: Drawing a Square
delete circle;
delete square;
return 0;
}
工厂方法模式:
创建抽象工厂类,每一个产品对应一个产品工厂。
cpp
// 抽象工厂
class ShapeFactory {
public:
virtual Shape* createShape() = 0;
virtual ~ShapeFactory() {}
};
// 圆形工厂
class CircleFactory : public ShapeFactory {
public:
Shape* createShape() override {
return new Circle();
}
};
// 方形工厂
class SquareFactory : public ShapeFactory {
public:
Shape* createShape() override {
return new Square();
}
};
// 客户端使用
ShapeFactory* factory = new CircleFactory();
Shape* shape = factory->createShape();
抽象工厂模式:
针对 多个产品族 的创建

cpp
#include <iostream>
// ----------------- 抽象产品接口 -----------------
// 抽象按钮
class Button {
public:
virtual void render() = 0;
virtual ~Button() {}
};
// 抽象复选框
class Checkbox {
public:
virtual void check() = 0;
virtual ~Checkbox() {}
};
// ----------------- 具体产品实现 -----------------
// Windows 按钮
class WindowsButton : public Button {
public:
void render() override {
std::cout << "Windows 风格按钮渲染" << std::endl;
}
};
// Windows 复选框
class WindowsCheckbox : public Checkbox {
public:
void check() override {
std::cout << "Windows 复选框被勾选" << std::endl;
}
};
// Mac 按钮
class MacButton : public Button {
public:
void render() override {
std::cout << "Mac 风格按钮渲染" << std::endl;
}
};
// Mac 复选框
class MacCheckbox : public Checkbox {
public:
void check() override {
std::cout << "Mac 复选框被勾选" << std::endl;
}
};
// ----------------- 抽象工厂接口 -----------------
class GUIFactory {
public:
virtual Button* createButton() = 0;
virtual Checkbox* createCheckbox() = 0;
virtual ~GUIFactory() {}
};
// ----------------- 具体工厂实现 -----------------
class WindowsFactory : public GUIFactory {
public:
Button* createButton() override {
return new WindowsButton();
}
Checkbox* createCheckbox() override {
return new WindowsCheckbox();
}
};
class MacFactory : public GUIFactory {
public:
Button* createButton() override {
return new MacButton();
}
Checkbox* createCheckbox() override {
return new MacCheckbox();
}
};
// ----------------- 客户端代码 -----------------
int main() {
// 假设根据当前系统选择工厂
GUIFactory* factory;
// 模拟配置:选择 Windows 或 Mac 工厂
std::string os = "Windows";
if (os == "Windows") {
factory = new WindowsFactory();
} else {
factory = new MacFactory();
}
// 使用工厂创建一组组件
Button* button = factory->createButton();
Checkbox* checkbox = factory->createCheckbox();
button->render(); // 输出对应系统的按钮渲染
checkbox->check(); // 输出对应系统的复选框行为
delete factory;
delete button;
delete checkbox;
return 0;
}
简单工厂 vs 工厂方法 vs 抽象工厂?
-
简单工厂:一个工厂类负责所有产品。
-
工厂方法:每个产品对应一个工厂子类。
-
抽象工厂:生产一个产品家族(例如不同风格的 UI 组件)。
单例模式:
单例设计模式(Singleton Pattern) 是一种创建型设计模式,用于确保一个类只有一个实例,并提供一个全局访问点来访问该实例。单例模式无法被回收,他的生命周期随进程,可以手动释放或者使用智能指针进行管理。
饿汉模式
饿汉模式:饿汉非常简单,定义静态实例,静态方法在加载到内存时就全部加载出来,缺陷是如果很大启动时就会花很长时间。
cpp
class Singleton {
private:
static Singleton instance; // 静态实例
Singleton() {} // 私有构造函数
// 禁止拷贝构造函数和赋值操作符,防止拷贝
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
public:
static Singleton* getInstance() {
return &instance; // 直接返回静态实例的地址
}
};
// 在类外部初始化静态实例
Singleton Singleton::instance;
懒汉模式
懒汉模式:懒汉的核心思想是"延迟加载",使用时再创建实例,使用双重检查锁确保线程安全和同步开销。
cpp
#include <mutex>
class Singleton {
private:
static Singleton* instance; // 静态实例指针
static std::mutex mutex; // 互斥锁,用于线程同步
Singleton() {} // 私有构造函数
// 禁止拷贝构造函数和赋值操作符,防止拷贝
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
public:
static Singleton* getInstance() {
if (instance == nullptr) { // 双重检查锁定(Double-Checked Locking)
std::lock_guard<std::mutex> lock(mutex); // 加锁
if (instance == nullptr) { // 再次检查实例是否已创建
instance = new Singleton(); // 如果未创建,则创建实例
}
}
return instance; // 返回实例的地址
}
};
// 在类外部初始化静态实例指针和互斥锁
Singleton* Singleton::instance = nullptr;
std::mutex Singleton::mutex;
Meyer's Singleton
使用静态局部变量实现的单例模式。静态局部变量的初始化是线程安全的。编译器会确保静态局部变量只被初始化一次,即使多个线程同时调用 getInstance()
。同时避免了资源浪费。实现简单,是现代 C++ 中推荐的单例实现方式。
cpp
class Singleton {
private:
Singleton() {} // 私有构造函数
Singleton(const Singleton&) = delete; // 禁止拷贝构造
Singleton& operator=(const Singleton&) = delete; // 禁止赋值操作
public:
static Singleton& getInstance() {
static Singleton instance; // 静态局部变量
return instance;
}
void doSomething() {
std::cout << "Singleton is doing something!" << std::endl;
}
};
应用场景:
线程池,内存池
结构型模式:
结构型模式:把类和对象结合在一起形成一个更大的结构。
行为型模式:
行为性模式:类和对象如何交互,划分责任和算法。
策略模式:
允许使用者根据不同的情况选择不同的策略(算法或行为)执行。
-
抽象策略接口(
SortStrategy
)定义所有具体策略必须实现的方法(如
sort()
)。 -
具体策略类(
BubbleSort
、QuickSort
)实现具体的算法逻辑。
-
上下文类(
Sorter
)-
持有策略对象的引用(通过组合关系)。
-
提供设置策略的方法(
setStrategy()
)和执行策略的方法(executeSort()
)。
-
cpp
#include <iostream>
#include <vector>
#include <memory>
// ----------------- 1. 抽象策略接口 -----------------
class SortStrategy {
public:
virtual void sort(std::vector<int>& data) = 0;
virtual ~SortStrategy() {} // 虚析构确保正确释放资源
};
// ----------------- 2. 具体策略类 -----------------
// 冒泡排序策略
class BubbleSort : public SortStrategy {
public:
void sort(std::vector<int>& data) override {
std::cout << "使用冒泡排序" << std::endl;
// 实现冒泡排序逻辑...
}
};
// 快速排序策略
class QuickSort : public SortStrategy {
public:
void sort(std::vector<int>& data) override {
std::cout << "使用快速排序" << std::endl;
// 实现快速排序逻辑...
}
};
// ----------------- 3. 上下文类(Context) -----------------
class Sorter {
private:
std::unique_ptr<SortStrategy> strategy; // 使用智能指针管理策略对象
public:
// 设置策略
void setStrategy(std::unique_ptr<SortStrategy> newStrategy) {
strategy = std::move(newStrategy);
}
// 执行排序
void executeSort(std::vector<int>& data) {
if (strategy) {
strategy->sort(data);
} else {
std::cout << "未设置排序策略!" << std::endl;
}
}
};
// ----------------- 客户端代码 -----------------
int main() {
Sorter sorter;
std::vector<int> data = {5, 2, 7, 1, 3};
// 动态切换策略
sorter.setStrategy(std::make_unique<BubbleSort>());
sorter.executeSort(data); // 输出:使用冒泡排序
sorter.setStrategy(std::make_unique<QuickSort>());
sorter.executeSort(data); // 输出:使用快速排序
return 0;
}
应用场景:
游戏中的角色行为:角色根据状态切换攻击、防御、逃跑策略。
动态使用不同的算法。
观察者模式:
定义对象间的一对多依赖关系,当一个对象(主题)状态改变时,所有依赖它的对象(观察者)会自动收到通知并更新。
应用场景:订阅-通知机制,实现松耦合的一对多事件处理。比如气象观测,观测机器观察到了数据,通知各类的软件。
中介者模式:
用一个中介对象(Mediator)来封装一组对象(Colleague)之间的交互,从而减少对象间的直接耦合。所有对象通过中介者通信,而不是直接相互引用。
应用场景:聊天室
模版模式:
在父类中定义一个规定了算法的执行步骤和顺序的模板方法,声明为 final,再将
算法中的步骤声明为抽象方法或虚函数,由子类具体实现。
cpp
#include <iostream>
// 抽象基类:定义饮料制作的模板
class Beverage {
public:
// 模板方法(final 禁止子类修改流程)
void prepareBeverage() final {
boilWater();
brew();
addCondiments();
pourInCup();
}
protected:
// 具体步骤由子类实现
virtual void brew() = 0;
virtual void addCondiments() = 0;
// 公共步骤(直接复用)
void boilWater() {
std::cout << "煮沸水" << std::endl;
}
void pourInCup() {
std::cout << "倒入杯子" << std::endl;
}
virtual ~Beverage() = default;
};
// 具体子类:咖啡
class Coffee : public Beverage {
protected:
void brew() override {
std::cout << "冲泡咖啡粉" << std::endl;
}
void addCondiments() override {
std::cout << "加糖和牛奶" << std::endl;
}
};
// 具体子类:茶
class Tea : public Beverage {
protected:
void brew() override {
std::cout << "浸泡茶叶" << std::endl;
}
void addCondiments() override {
std::cout << "加柠檬" << std::endl;
}
};
// 客户端代码
int main() {
Beverage* coffee = new Coffee();
coffee->prepareBeverage();
// 输出:
// 煮沸水
// 冲泡咖啡粉
// 加糖和牛奶
// 倒入杯子
Beverage* tea = new Tea();
tea->prepareBeverage();
// 输出:
// 煮沸水
// 浸泡茶叶
// 加柠檬
// 倒入杯子
delete coffee;
delete tea;
return 0;
}
应用场景:
比如餐厅服务员的游戏,制作可乐,雪碧什么的饮料都是一样的步骤,就可以设定一个制作饮料的类,里面规定制作饮料的步骤。