一文学会设计模式之结构型模式及最佳实现

口诀

控制访问用代理 ,接口不兼容用适配 ,抽象实现分桥接 ,动态功能用装饰 ,统一接口用外观 ,大量对象用享元 ,树形结构用组合

结构型设计模式对比表

模式 核心用途 适用场景 关键特点 C++最佳实现
代理 控制对象访问 延迟加载/权限控制 不修改原对象 std::shared_ptr 管理代理对象
适配器 接口转换 第三方库集成 接口不兼容转换 适配器 std::shared_ptr 持有被适配者
桥接 分离抽象与实现 多维度变化(如形状+绘制方式) 避免类爆炸 用组合代替继承,std::shared_ptr 桥接
装饰 动态添加功能 日志/权限等扩展 比继承更灵活 装饰器继承组件接口并持有组件对象
外观 简化复杂系统 多子系统整合 统一高层接口 统一接口,外观类管理多子系统
享元 对象复用 大量相似对象(字符/像素) 减少内存占用 工厂管理共享对象,std::map 实现
组合 树形结构统一处理 文件系统/组织架构 叶子/组合统一调用 std::vectorstd::shared_ptr 存储子组件

结构型设计模式全解析

1. 代理模式 (Proxy)

关键点

  • 为对象提供代理以控制访问
  • 代理与真实对象实现相同接口
  • 用于权限控制、延迟初始化、日志记录等

优缺点

优点 缺点
增加功能而不修改真实对象 代理可能增加性能开销
客户端与真实对象解耦 增加系统复杂度
便于实现权限控制和延迟加载

C++最佳实现(详细类解释)

cpp 复制代码
// 抽象对象:定义客户端和真实对象的接口
class Subject {
public:
    virtual void request() = 0; // 纯虚函数,定义请求接口
    virtual ~Subject() = default; // 虚析构函数,确保正确销毁
};

// 真实对象:实现具体业务逻辑
class RealSubject : public Subject {
public:
    void request() override {
        std::cout << "RealSubject: Handling request.\n";
    }
};

// 代理类:控制对真实对象的访问
class Proxy : public Subject {
private:
    std::shared_ptr<RealSubject> realSubject; // 持有真实对象的智能指针

public:
    Proxy() : realSubject(nullptr) {} // 初始化为nullptr

    void request() override {
        // 延迟初始化:首次调用时创建真实对象
        if (!realSubject) {
            realSubject = std::make_shared<RealSubject>();
        }
        std::cout << "Proxy: Checking access prior to firing real request.\n";
        realSubject->request(); // 调用真实对象的方法
    }
};

调用方式

cpp 复制代码
auto subject = std::make_shared<Proxy>();
subject->request(); // 通过代理调用,实际执行真实对象方法

类图关系(UML标准表示)
has a <<interface>> Subject +request() RealSubject +request() Proxy +request()


2. 适配器模式 (Adapter)

关键点

  • 将不兼容接口转换为客户端期望的接口
  • 通过组合实现,避免继承导致的类爆炸
  • 适用于集成已有类库

优缺点

优点 缺点
无需修改现有代码 适配器可能包含业务逻辑
使不兼容接口协同工作 增加系统复杂度
适合已有类库的集成

C++最佳实现(对象适配器)

cpp 复制代码
// 目标接口:客户端期望的接口
class Target {
public:
    virtual void request() = 0;
    virtual ~Target() = default;
};

// 被适配者:已有类,接口不兼容
class Adaptee {
public:
    void specificRequest() {
        std::cout << "Adaptee: Specific request.\n";
    }
};

// 适配器:实现目标接口,适配被适配者
class Adapter : public Target {
private:
    std::shared_ptr<Adaptee> adaptee; // 持有被适配者对象

public:
    Adapter(std::shared_ptr<Adaptee> adaptee) : adaptee(adaptee) {}

    void request() override {
        adaptee->specificRequest(); // 调用被适配者的方法
    }
};

调用方式

cpp 复制代码
auto adaptee = std::make_shared<Adaptee>();
auto adapter = std::make_shared<Adapter>(adaptee);
adapter->request(); // 通过适配器转换调用

类图关系(UML标准表示)
has a <<interface>> Target +request() Adaptee +specificRequest() Adapter +request()


3. 桥接模式 (Bridge)

关键点

  • 将抽象与实现分离,使它们可以独立变化
  • 用组合代替继承,避免"形状×绘制方式"类爆炸
  • 两个独立变化的维度:抽象(Shape)和实现(DrawingAPI)

优缺点

优点 缺点
抽象与实现解耦,独立变化 增加系统复杂度
避免类爆炸(组合爆炸) 需要额外接口设计
适合多维度变化的场景

C++最佳实现(详细类解释)

简单点儿说,将一个维度作为成员变量。

cpp 复制代码
// 实现接口:定义实现部分的接口
class DrawingAPI {
public:
    virtual void drawCircle(double x, double y, double radius) = 0;
    virtual ~DrawingAPI() = default;
};

// 具体实现1:矢量绘制
class VectorDrawingAPI : public DrawingAPI {
public:
    void drawCircle(double x, double y, double radius) override {
        std::cout << "VectorAPI: Drawing circle at (" << x << ", " << y 
                  << ") with radius " << radius << "\n";
    }
};

// 具体实现2:位图绘制
class BitmapDrawingAPI : public DrawingAPI {
public:
    void drawCircle(double x, double y, double radius) override {
        std::cout << "BitmapAPI: Drawing circle at (" << x << ", " << y 
                  << ") with radius " << radius << "\n";
    }
};

// 抽象类:定义抽象部分的接口
class Shape {
protected:
    std::shared_ptr<DrawingAPI> drawingAPI; // 持有实现对象

public:
    Shape(std::shared_ptr<DrawingAPI> api) : drawingAPI(api) {}

    virtual void draw() = 0; // 抽象方法
    virtual ~Shape() = default;
};

// 扩展抽象:圆形
class CircleShape : public Shape {
private:
    double x, y, radius;
public:
    CircleShape(double x, double y, double radius, std::shared_ptr<DrawingAPI> api)
        : Shape(api), x(x), y(y), radius(radius) {}

    void draw() override {
        drawingAPI->drawCircle(x, y, radius); // 调用实现接口
    }
};

// 扩展抽象:方形
class SquareShape : public Shape {
private:
    double x, y, side;
public:
    SquareShape(double x, double y, double side, std::shared_ptr<DrawingAPI> api)
        : Shape(api), x(x), y(y), side(side) {}

    void draw() override {
        std::cout << "SquareShape: Drawing square at (" << x << ", " << y 
                  << ") with side " << side << " using ";
        drawingAPI->drawCircle(0, 0, 0); // 通过API模拟绘制
    }
};

调用方式

cpp 复制代码
auto vectorAPI = std::make_shared<VectorDrawingAPI>();
auto bitmapAPI = std::make_shared<BitmapDrawingAPI>();

auto circleVector = std::make_shared<CircleShape>(1.0, 2.0, 3.0, vectorAPI);
auto circleBitmap = std::make_shared<CircleShape>(1.0, 2.0, 3.0, bitmapAPI);
auto squareVector = std::make_shared<SquareShape>(5.0, 6.0, 4.0, vectorAPI);

circleVector->draw();  // 使用矢量API绘制圆形
circleBitmap->draw();  // 使用位图API绘制圆形
squareVector->draw();  // 使用矢量API绘制方形

类图关系(UML标准表示)
implements <<interface>> DrawingAPI +drawCircle(x, y, radius) VectorDrawingAPI +drawCircle(x, y, radius) BitmapDrawingAPI +drawCircle(x, y, radius) <<abstract>> Shape -drawingAPI: DrawingAPI +draw() CircleShape +draw() SquareShape +draw()


4. 装饰模式 (Decorator)

关键点

  • 动态地给对象添加额外职责
  • 通过组合实现,避免继承导致的类爆炸
  • 装饰类与被装饰类实现相同接口

优缺点

优点 缺点
灵活性高,可动态添加功能 可能导致设计过于复杂
避免类爆炸(继承方式) 对象数量增加
可组合多个装饰

C++最佳实现(详细类解释)

简单点儿说,装饰器基类继承组件并持有组件对象,装饰器子类添加额外功能。

cpp 复制代码
// 组件接口:定义基本接口
class Component {
public:
    virtual void operation() = 0;
    virtual ~Component() = default;
};

// 具体组件:实现基本功能
class ConcreteComponent : public Component {
public:
    void operation() override {
        std::cout << "ConcreteComponent: Basic operation.\n";
    }
};

// 装饰器基类:继承组件接口,持有一个组件对象
class Decorator : public Component {
protected:
    std::shared_ptr<Component> component; // 持有被装饰对象

public:
    Decorator(std::shared_ptr<Component> comp) : component(comp) {}

    void operation() override {
        component->operation(); // 调用被装饰对象的基本操作
    }
};

// 具体装饰器1:添加额外功能
class ConcreteDecoratorA : public Decorator {
public:
    ConcreteDecoratorA(std::shared_ptr<Component> comp) : Decorator(comp) {}

    void operation() override {
        Decorator::operation(); // 先调用基础操作
        addedBehavior(); // 添加额外行为
    }

    void addedBehavior() {
        std::cout << "ConcreteDecoratorA: Added behavior.\n";
    }
};

// 具体装饰器2:添加另一额外功能
class ConcreteDecoratorB : public Decorator {
public:
    ConcreteDecoratorB(std::shared_ptr<Component> comp) : Decorator(comp) {}

    void operation() override {
        Decorator::operation();
        addedBehavior();
    }

    void addedBehavior() {
        std::cout << "ConcreteDecoratorB: Added behavior.\n";
    }
};

调用方式

cpp 复制代码
auto component = std::make_shared<ConcreteComponent>();
auto decoratorA = std::make_shared<ConcreteDecoratorA>(component);
auto decoratorB = std::make_shared<ConcreteDecoratorB>(decoratorA);

decoratorB->operation(); // 依次执行:Basic → A → B

类图关系(UML标准表示)
has a <<interface>> Component +operation() ConcreteComponent +operation() Decorator +operation() ConcreteDecoratorA +addedBehavior() +operation() ConcreteDecoratorB +addedBehavior() +operation()


5. 外观模式 (Facade)

关键点

  • 为复杂子系统提供统一接口
  • 客户端通过外观类与子系统交互
  • 屏蔽子系统的复杂性

优缺点

优点 缺点
简化接口,降低使用难度 增加额外外观类
降低客户端与子系统的耦合 可能隐藏子系统细节
适合复杂子系统

C++最佳实现(详细类解释)

cpp 复制代码
// 子系统1
class Subsystem1 {
public:
    void operation1() {
        std::cout << "Subsystem1: Operation1.\n";
    }
};

// 子系统2
class Subsystem2 {
public:
    void operation2() {
        std::cout << "Subsystem2: Operation2.\n";
    }
};

// 外观类:提供统一接口
class Facade {
private:
    std::shared_ptr<Subsystem1> subsystem1;
    std::shared_ptr<Subsystem2> subsystem2;

public:
    Facade() : subsystem1(std::make_shared<Subsystem1>()),
               subsystem2(std::make_shared<Subsystem2>()) {}

    void operation() {
        subsystem1->operation1(); // 调用子系统1
        subsystem2->operation2(); // 调用子系统2
    }
};

调用方式

cpp 复制代码
auto facade = std::make_shared<Facade>();
facade->operation(); // 通过外观简化调用

类图关系(UML标准表示)
uses uses Facade +operation() Subsystem1 +operation1() Subsystem2 +operation2()


6. 享元模式 (Flyweight)

关键点

  • 通过共享技术支持大量细粒度对象
  • 分离内部状态(共享)和外部状态(不共享)
  • 减少内存消耗

优缺点

优点 缺点
减少内存使用 实现复杂
适合大量相似对象,提高性能 需要管理共享对象

C++最佳实现(详细类解释)

cpp 复制代码
// 享元接口
class Flyweight {
public:
    virtual void operation(std::string extrinsicState) = 0;
    virtual ~Flyweight() = default;
};

// 具体享元:实现共享状态
class ConcreteFlyweight : public Flyweight {
public:
    void operation(std::string extrinsicState) override {
        std::cout << "ConcreteFlyweight: " << extrinsicState << "\n";
    }
};

// 享元工厂:管理共享对象
class FlyweightFactory {
private:
    std::map<std::string, std::shared_ptr<Flyweight>> flyweights;

public:
    std::shared_ptr<Flyweight> getFlyweight(std::string key) {
        if (flyweights.find(key) == flyweights.end()) {
            flyweights[key] = std::make_shared<ConcreteFlyweight>();
        }
        return flyweights[key];
    }
};

调用方式

cpp 复制代码
auto factory = std::make_shared<FlyweightFactory>();
auto flyweight1 = factory->getFlyweight("key1");
auto flyweight2 = factory->getFlyweight("key2");

flyweight1->operation("State1"); // 共享对象,外部状态不同
flyweight2->operation("State2");

类图关系(UML标准表示)
creates <<interface>> Flyweight +operation(extrinsicState) ConcreteFlyweight +operation(extrinsicState) FlyweightFactory +getFlyweight(key)


7. 组合模式 (Composite)

关键点

  • 将对象组合成树形结构表示"部分-整体"层次
  • 客户端统一处理单个对象和组合对象
  • 使客户端无需区分处理的是叶子还是组合

优缺点

优点 缺点
统一处理个体与组合 增加系统复杂度
适合树形结构,简化客户端代码 需要定义组合结构

C++最佳实现(详细类解释)

父节点跟子节点属性是一样的,所以都继承于Component,这里父节点添加额外成员children。

cpp 复制代码
// 组件接口
class Component {
public:
    virtual void add(std::shared_ptr<Component> component) = 0;
    virtual void remove(std::shared_ptr<Component> component) = 0;
    virtual void operation() = 0;
    virtual ~Component() = default;
};

// 叶子节点:没有子节点
class Leaf : public Component {
public:
    void add(std::shared_ptr<Component>) override {} // 无子节点,不实现
    void remove(std::shared_ptr<Component>) override {} // 无子节点,不实现
    void operation() override {
        std::cout << "Leaf: Operation.\n";
    }
};

// 组合节点:包含子节点
class Composite : public Component {
private:
    std::vector<std::shared_ptr<Component>> children;

public:
    void add(std::shared_ptr<Component> component) override {
        children.push_back(component);
    }

    void remove(std::shared_ptr<Component> component) override {
        children.erase(std::remove(children.begin(), children.end(), component), children.end());
    }

    void operation() override {
        std::cout << "Composite: Operation.\n";
        for (const auto& child : children) {
            child->operation(); // 递归调用子节点
        }
    }
};

调用方式

cpp 复制代码
auto leaf1 = std::make_shared<Leaf>();
auto leaf2 = std::make_shared<Leaf>();
auto composite = std::make_shared<Composite>();

composite->add(leaf1);
composite->add(leaf2);
composite->operation(); // 统一调用组合和叶子

类图关系(UML标准表示)
contains <<interface>> Component +add(component) +remove(component) +operation() Leaf +operation() Composite +add(component) +remove(component) +operation()

相关推荐
A7bert7774 小时前
【YOLOv5seg部署RK3588】模型训练→转换RKNN→开发板部署
linux·c++·人工智能·深度学习·yolo·目标检测
历程里程碑5 小时前
C++ 10 模板进阶:参数特化与分离编译解析
c语言·开发语言·数据结构·c++·算法
老秦包你会5 小时前
C++进阶------智能指针和特殊类设计方式
开发语言·c++
code bean5 小时前
【CMake 】[第十篇]CMake find_package 完全指南:让第三方库集成变得简单
c++·cmake
IT19956 小时前
C++使用“长度前缀法”解决TCP“粘包 / 拆包”问题
服务器·网络·c++·tcp/ip
Tipriest_6 小时前
旋转矩阵,齐次变换矩阵,欧拉角,四元数等相互转换的常用代码C++ Python
c++·python·矩阵
hz_zhangrl6 小时前
CCF-GESP 等级考试 2025年9月认证C++六级真题解析
c++·算法·青少年编程·程序设计·gesp·2025年9月gesp·gesp c++六级
兵哥工控6 小时前
MFC用高精度计时器实现五段时序控制器
c++·mfc·高精度计时器·时序控制器
眠りたいです7 小时前
基于脚手架微服务的视频点播系统-服务端开发部分(补充)文件子服务问题修正
c++·微服务·云原生·架构