Skip to Main Content
23 种设计模式 · C++ 版优缺点与应用场景Back to Top

23 种设计模式 · C++ 版优缺点与应用场景

12 minutes

23 种设计模式 · C++ 版优缺点与应用场景

GoF《设计模式》23 种,按目的分三类:创建型(5)· 结构型(7)· 行为型(11)。本文给出每种模式的意图、C++ 关键代码、优缺点与典型应用场景。


总览

类别模式一句话
创建型单例 Singleton全局唯一实例
创建型工厂方法 Factory Method子类决定创建哪个类
创建型抽象工厂 Abstract Factory创建一族相关对象
创建型建造者 Builder分步构建复杂对象
创建型原型 Prototype复制已有对象
结构型适配器 Adapter接口转换
结构型桥接 Bridge抽象与实现分离
结构型组合 Composite树形整体-部分
结构型装饰 Decorator动态附加职责
结构型外观 Facade统一门面接口
结构型享元 Flyweight共享细粒度对象
结构型代理 Proxy替身控制访问
行为型责任链 Chain of Responsibility请求沿链传递
行为型命令 Command请求封装为对象
行为型解释器 Interpreter文法解释
行为型迭代器 Iterator顺序访问集合
行为型中介者 Mediator对象间解耦通信
行为型备忘录 Memento保存/恢复状态
行为型观察者 Observer一对多通知
行为型状态 State状态行为切换
行为型策略 Strategy算法族可替换
行为型模板方法 Template Method骨架固定、步骤可变
行为型访问者 Visitor数据结构与操作分离

一、创建型模式

1. 单例 Singleton

意图:确保一个类只有一个实例,并提供全局访问点。

class Logger {
public:
    static Logger& instance() {
        static Logger inst;  // C++11 线程安全
        return inst;
    }
private:
    Logger() = default;
};
优点缺点
全局唯一、省资源隐藏依赖,难测试
延迟初始化多线程初始化需注意

场景:日志系统、配置中心、线程池、连接池。

2. 工厂方法 Factory Method

意图:定义一个创建对象的接口,让子类决定实例化哪个类。

struct Product { virtual ~Product() = default; };
struct ConcreteA : Product {};

class Factory {
public:
    virtual std::unique_ptr<Product> create() = 0;
};
class FactoryA : public Factory {
    std::unique_ptr<Product> create() override { return std::make_unique<ConcreteA>(); }
};
优点缺点
解耦创建与使用每加一个产品需加子类
开闭原则友好类数量膨胀

场景:框架中由子类决定对象类型(如游戏单位工厂)。

3. 抽象工厂 Abstract Factory

意图:提供创建一族相关对象的接口。

struct Button { virtual ~Button() = default; };
struct WinButton : Button {};

class UIFactory {
public:
    virtual std::unique_ptr<Button> makeButton() = 0;
};
class WinFactory : public UIFactory {
    std::unique_ptr<Button> makeButton() override { return std::make_unique<WinButton>(); }
};
优点缺点
保证产品族一致新增产品族类型困难
隔离具体类新增产品(方法)违反开闭

场景:跨平台 UI 组件、数据库访问层(不同方言)。

4. 建造者 Builder

意图:分步骤构建复杂对象,步骤可复用于不同表示。

class PizzaBuilder {
public:
    PizzaBuilder& size(int s) { size_ = s; return *this; }
    Pizza build() { return Pizza(size_); }
private:
    int size_ = 0;
};
// 使用:PizzaBuilder{}.size(12).build();
优点缺点
构造参数可读、不可变需要额外类
复用构建流程简单对象反而过度设计

场景:复杂配置对象、文档/查询构建器。

5. 原型 Prototype

意图:通过克隆已有对象创建新对象。

struct Shape {
    virtual ~Shape() = default;
    virtual std::unique_ptr<Shape> clone() const = 0;
};
struct Circle : Shape {
    std::unique_ptr<Shape> clone() const override {
        return std::make_unique<Circle>(*this);
    }
};
优点缺点
避免重复构造开销深拷贝语义易出错
动态类型克隆含资源成员需自定义拷贝

场景:编辑器复制图形、游戏单位克隆、配置模板。


二、结构型模式

6. 适配器 Adapter

意图:将不兼容接口转换为客户端期望的接口。

class Target { public: virtual void request() = 0; };
class Adaptee { public: void specific() {} };
class Adapter : public Target {
public:
    void request() override { adaptee_.specific(); }
private:
    Adaptee adaptee_;
};
优点缺点
复用已有类,不改源码过度使用使架构混乱
符合开闭原则有性能微开销

场景:接入第三方库、新旧接口桥接。

7. 桥接 Bridge

意图:将抽象部分与实现部分分离,各自独立变化。

class Renderer { public: virtual void draw() = 0; };
class Shape {
public:
    explicit Shape(Renderer* r) : r_(r) {}
protected:
    Renderer* r_;
};
class Circle : public Shape {
public:
    using Shape::Shape;
    void draw() { r_->draw(); }
};
优点缺点
抽象与实现可独立扩展增加系统复杂度
符合开闭原则需提前识别维度

场景:图形渲染后端(OpenGL/Vulkan)、跨平台设备驱动。

8. 组合 Composite

意图:将对象组织成树形结构,一致对待叶子与容器。

class Component {
public:
    virtual void render() = 0;
    virtual void add(Component*) {}
};
class Leaf : public Component { void render() override {} };
class Composite : public Component {
public:
    void add(Component* c) override { children_.push_back(c); }
    void render() override { for (auto* c : children_) c->render(); }
private:
    std::vector<Component*> children_;
};
优点缺点
树形结构统一操作叶子与容器接口耦合
易扩展新节点违反接口隔离

场景:文件系统、UI 控件树、组织架构。

9. 装饰 Decorator

意图:动态给对象添加职责,替代继承。

class Stream { public: virtual void write(const std::string&) = 0; };
class FileStream : public Stream { void write(const std::string& s) override {} };
class EncryptedStream : public Stream {
public:
    explicit EncryptedStream(Stream* s) : s_(s) {}
    void write(const std::string& s) override { s_->write(encrypt(s)); }
private:
    Stream* s_;
};
优点缺点
组合优于继承,灵活层数多时难调试
运行时叠加能力小对象过多

场景:IO 流加缓冲/加密/压缩、中间件管道。

10. 外观 Facade

意图:为复杂子系统提供统一简化的入口。

class VideoConverter {
public:
    void convert(const std::string& file) {
        codec_.load(file);
        filter_.apply();
        mux_.save();
    }
private:
    Codec codec_; Filter filter_; Muxer mux_;
};
优点缺点
客户端使用简单可能变成“上帝对象“
隔离子系统变化隐藏了灵活性

场景:编译模块入口、播放器/转换器统一 API。

11. 享元 Flyweight

意图:共享细粒度对象,减少内存占用。

struct CharStyle { std::string font; int size; };
class StyleCache {
public:
    const CharStyle& get(const std::string& font, int size) {
        auto key = font + std::to_string(size);
        auto it = cache_.find(key);
        if (it == cache_.end())
            it = cache_.emplace(key, CharStyle{font, size}).first;
        return it->second;
    }
private:
    std::unordered_map<std::string, CharStyle> cache_;
};
优点缺点
大幅减少内存外部状态管理复杂
提高缓存命中引入共享对象并发问题

场景:文本编辑器字符样式、游戏贴图/粒子模板、连接池。

12. 代理 Proxy

意图:提供替身控制对真实对象的访问(延迟/权限/缓存)。

class Image { public: virtual void show() = 0; };
class RealImage : public Image { void show() override {} };
class ImageProxy : public Image {
public:
    void show() override {
        if (!real_) real_ = std::make_unique<RealImage>();
        real_->show();          // 延迟加载
    }
private:
    std::unique_ptr<RealImage> real_;
};
优点缺点
延迟加载、访问控制、日志增加间接层
透明代理过度代理增加延迟

场景:懒加载图片、智能指针、远程调用(RPC stub)。


三、行为型模式

13. 责任链 Chain of Responsibility

意图:多个处理者串成链,请求沿链传递直到被处理。

class Handler {
public:
    Handler* next(Handler* n) { next_ = n; return this; }
    virtual void handle(int level) {
        if (canHandle(level)) process();
        else if (next_) next_->handle(level);
    }
private:
    virtual bool canHandle(int) = 0;
    virtual void process() = 0;
    Handler* next_ = nullptr;
};
优点缺点
发送者与处理者解耦请求可能无人处理
灵活增删处理者调试链长时困难

场景:日志级别过滤、事件冒泡、中间件管道。

14. 命令 Command

意图:把请求封装成对象,支持参数化、队列、撤销。

class Command {
public:
    virtual void execute() = 0;
    virtual void undo() = 0;
};
class CopyCommand : public Command {
    void execute() override {}
    void undo() override {}
};
优点缺点
支持撤销/重做、任务队列每个操作一个类
请求可参数化延迟执行类数量增加

场景:编辑器撤销栈、事务、宏录制、线程任务。

15. 解释器 Interpreter

意图:为文法定义解释器,求值表达式。

struct Expr { virtual int eval() const = 0; };
struct Num : Expr { int v; int eval() const override { return v; } };
struct Add : Expr {
    const Expr *l, *r;
    int eval() const override { return l->eval() + r->eval(); }
};
优点缺点
文法易扩展复杂文法维护困难
领域语言表达力强性能较低

场景:SQL/正则/数学表达式引擎、脚本解析。

16. 迭代器 Iterator

意图:不暴露内部结构,顺序访问集合元素。

class Iter {
public:
    virtual bool hasNext() = 0;
    virtual int next() = 0;
};
class RangeIter : public Iter {
    int cur_, end_;
public:
    RangeIter(int a, int b) : cur_(a), end_(b) {}
    bool hasNext() override { return cur_ <= end_; }
    int next() override { return cur_++; }
};
优点缺点
集合遍历与结构解耦简单集合反而多余
支持多种遍历策略遍历中修改集合需约定

场景:STL 迭代器、分页遍历、树遍历。

17. 中介者 Mediator

意图:用一个中介对象协调多个对象的交互。

class Mediator {
public:
    void notify(const std::string& from, const std::string& msg) {
        for (auto* c : colleagues_) if (c->name() != from) c->receive(msg);
    }
    void add(Colleague* c) { colleagues_.push_back(c); }
private:
    std::vector<Colleague*> colleagues_;
};
优点缺点
减少对象间网状依赖中介者可能过于庞大
交互集中管理单点故障

场景:聊天室、UI 控件协调、航班调度。

18. 备忘录 Memento

意图:在不破坏封装的前提下保存并恢复对象状态。

struct Memento { int state; };
class Originator {
public:
    Memento save() const { return {state_}; }
    void restore(const Memento& m) { state_ = m.state; }
private:
    int state_ = 0;
};
优点缺点
状态快照与恢复简单大对象快照开销高
不破坏封装历史过多占内存

场景:编辑器撤销、游戏存档、事务回滚。

19. 观察者 Observer

意图:定义一对多依赖,状态变化自动通知。

class Observer { public: virtual void update() = 0; };
class Subject {
public:
    void attach(Observer* o) { obs_.push_back(o); }
    void notify() { for (auto* o : obs_) o->update(); }
private:
    std::vector<Observer*> obs_;
};
优点缺点
主题与观察者解耦通知顺序不确定
广播机制天然级联更新难排查

场景:事件总线、MVC 视图刷新、发布订阅。

20. 状态 State

意图:对象状态改变时行为随之改变,替代大量 if-else。

class State { public: virtual void handle() = 0; };
class IdleState : public State { void handle() override {} };
class RunningState : public State { void handle() override {} };
优点缺点
状态行为内聚、可扩展状态类数量多
消除巨型条件分支状态转换逻辑分散

场景:播放器状态、订单状态机、网络连接状态。

21. 策略 Strategy

意图:定义算法族并封装,运行时切换。

class SortStrategy { public: virtual void sort(std::vector<int>&) = 0; };
class QuickSort : public SortStrategy { void sort(std::vector<int>& v) override {} };
class MergeSort : public SortStrategy { void sort(std::vector<int>& v) override {} };

class Sorter {
public:
    void setStrategy(SortStrategy* s) { s_ = s; }
    void run(std::vector<int>& v) { s_->sort(v); }
private:
    SortStrategy* s_;
};
优点缺点
算法可替换、开闭原则客户端需了解策略差异
消除条件分支策略对象数量增加

场景:排序算法选择、压缩/加密算法、价格计算。

22. 模板方法 Template Method

意图:定义算法骨架,子类实现可变步骤。

class DataParser {
public:
    void parse() {                 // 骨架固定
        open(); read(); process(); close();
    }
protected:
    virtual void process() = 0;    // 可变步骤
private:
    void open() {} void read() {} void close() {}
};
优点缺点
复用公共流程骨架修改影响全部子类
约束子类实现范围违反 LSP 风险(子类改变骨架)

场景:框架生命周期(初始化-运行-清理)、解析器流程。

23. 访问者 Visitor

意图:在不修改类的前提下,为对象结构增加新操作。

class Visitor; 
class Node {
public:
    virtual void accept(Visitor& v) = 0;
};
class TextNode : public Node {
public:
    void accept(Visitor& v) override;
};
class Visitor {
public:
    virtual void visit(TextNode&) = 0;
};
优点缺点
数据结构与操作分离,易加操作新增节点类型需改所有访问者
操作内聚破坏封装(需暴露内部)

场景:AST 编译/解释、对象结构统计与序列化。


选型速查

问题推荐模式
全局唯一单例
创建复杂对象建造者 / 工厂 / 抽象工厂
接口不兼容适配器
动态加职责装饰
树形结构组合
延迟/控制访问代理
一对多通知观察者
运行时换算法策略
状态行为切换状态
撤销重做命令 + 备忘录
为结构加新操作访问者

原则提醒:优先组合而非继承、面向接口而非实现、对扩展开放对修改关闭。模式是工具,不要为模式而模式。