跳转到内容

C++ 适配器模式

来自代码酷

C++适配器模式[编辑 | 编辑源代码]

适配器模式(Adapter Pattern)是一种结构型设计模式,它允许不兼容的接口之间进行协作。该模式通过将一个类的接口转换成客户端期望的另一个接口,使得原本由于接口不兼容而不能一起工作的类可以协同工作。

介绍[编辑 | 编辑源代码]

适配器模式在C++中常用于以下场景:

  • 将旧代码集成到新系统中
  • 使用第三方库时接口不匹配
  • 为不同的子系统提供统一的接口

适配器模式有两种主要实现方式: 1. 类适配器 - 通过多重继承实现 2. 对象适配器 - 通过组合实现

类适配器[编辑 | 编辑源代码]

类适配器使用多重继承来适配接口。它继承目标接口和被适配者类。

// 目标接口
class Target {
public:
    virtual ~Target() = default;
    virtual void request() = 0;
};

// 被适配者
class Adaptee {
public:
    void specificRequest() {
        std::cout << "Adaptee's specific request" << std::endl;
    }
};

// 类适配器
class ClassAdapter : public Target, private Adaptee {
public:
    void request() override {
        specificRequest(); // 调用被适配者的方法
    }
};

// 使用示例
int main() {
    Target* target = new ClassAdapter();
    target->request(); // 输出: Adaptee's specific request
    delete target;
    return 0;
}

对象适配器[编辑 | 编辑源代码]

对象适配器使用组合而非继承,这种方式更灵活,是更常用的实现方式。

// 目标接口
class Target {
public:
    virtual ~Target() = default;
    virtual void request() = 0;
};

// 被适配者
class Adaptee {
public:
    void specificRequest() {
        std::cout << "Adaptee's specific request" << std::endl;
    }
};

// 对象适配器
class ObjectAdapter : public Target {
private:
    Adaptee* adaptee;
public:
    ObjectAdapter(Adaptee* a) : adaptee(a) {}
    void request() override {
        adaptee->specificRequest(); // 委托给被适配者
    }
};

// 使用示例
int main() {
    Adaptee* adaptee = new Adaptee();
    Target* target = new ObjectAdapter(adaptee);
    target->request(); // 输出: Adaptee's specific request
    delete target;
    delete adaptee;
    return 0;
}

实际应用案例[编辑 | 编辑源代码]

案例:图形渲染接口适配

假设我们有一个现代图形库(ModernRenderer)和一个遗留图形库(LegacyRenderer),它们的接口不兼容:

// 现代图形接口
class ModernRenderer {
public:
    virtual void render(float x, float y, float width, float height) = 0;
};

// 遗留图形接口
class LegacyRenderer {
public:
    void draw(int x1, int y1, int x2, int y2) {
        std::cout << "Legacy renderer drawing from (" << x1 << "," << y1 
                  << ") to (" << x2 << "," << y2 << ")" << std::endl;
    }
};

// 适配器
class RendererAdapter : public ModernRenderer {
private:
    LegacyRenderer* legacyRenderer;
public:
    RendererAdapter(LegacyRenderer* renderer) : legacyRenderer(renderer) {}
    
    void render(float x, float y, float width, float height) override {
        // 将现代接口的参数转换为遗留接口的参数
        int x1 = static_cast<int>(x);
        int y1 = static_cast<int>(y);
        int x2 = static_cast<int>(x + width);
        int y2 = static_cast<int>(y + height);
        legacyRenderer->draw(x1, y1, x2, y2);
    }
};

// 使用示例
int main() {
    LegacyRenderer legacyRenderer;
    ModernRenderer* renderer = new RendererAdapter(&legacyRenderer);
    renderer->render(10.5f, 20.5f, 100.0f, 200.0f);
    // 输出: Legacy renderer drawing from (10,20) to (110,220)
    delete renderer;
    return 0;
}

类图[编辑 | 编辑源代码]

以下是适配器模式的类图表示:

classDiagram class Target { <<interface>> +request() } class Adaptee { +specificRequest() } class Adapter { -adaptee: Adaptee +request() } Target <|-- Adapter Adapter o-- Adaptee

优缺点[编辑 | 编辑源代码]

优点:

  • 使不兼容的接口能够协同工作
  • 遵循开闭原则(对扩展开放,对修改关闭)
  • 提高代码复用性

缺点:

  • 增加系统复杂性
  • 在某些情况下可能降低性能(由于额外的间接调用)

与其他模式的关系[编辑 | 编辑源代码]

  • 适配器模式与装饰器模式相似,但目的不同:适配器改变接口,装饰器增强功能。
  • 适配器模式与外观模式相似,但适配器通常包装单个类,而外观模式处理整个子系统。

总结[编辑 | 编辑源代码]

适配器模式是解决接口不兼容问题的有效工具。在C++中,对象适配器(使用组合)通常比类适配器(使用多重继承)更受欢迎,因为它更灵活且避免了多重继承的复杂性。当需要集成旧代码或第三方库时,适配器模式特别有用。