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

口诀

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

结构型设计模式对比表

模式 核心用途 适用场景 关键特点 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()

相关推荐
mingren_13141 天前
c++和qml交互
c++·qt·交互
cn_mengbei1 天前
鸿蒙PC上Qt原生应用开发:从零搭建开发环境到部署实战,附HarmonyOS SDK配置与避坑指南(C++实现)
c++·qt·harmonyos
脏脏a1 天前
手撕 vector:从 0 到 1 模拟实现 STL 容器
开发语言·c++·vector
郝学胜-神的一滴1 天前
Linux 读写锁深度解析:原理、应用与性能优化
linux·服务器·c++·程序人生·性能优化
闻缺陷则喜何志丹1 天前
【图论 DFS 换根法】3772. 子图的最大得分|2235
c++·算法·深度优先·力扣·图论·换根法
开开心心就好1 天前
音频格式互转工具,支持Mp3ApeWavFlac互转
java·网络·c++·windows·qt·电脑·excel
byxdaz1 天前
C++内存序
c++
优雅的潮叭1 天前
c++ 学习笔记之 malloc
c++·笔记·学习
苦藤新鸡1 天前
8.最长的无重复字符的子串
c++·力扣
꧁Q༒ོγ꧂1 天前
C++ 入门完全指南(四)--函数与模块化编程
开发语言·c++