C++适配器模式之可插入适配器的实现模式和方法

可插入适配器与Adaptee的窄接口

在C++适配器模式中,可插入适配器(Pluggable Adapter)是指适配器类的设计允许在运行时动态地插入不同的Adaptee对象,从而使适配器具有灵活性和可扩展性。这种设计使得适配器不仅限于适配一个特定的Adaptee,而是可以适配多个不同的Adaptee。

Adaptee的窄接口(Narrow Interface)是指Adaptee提供的接口只包含有限的方法,这些方法可能不足以满足客户端的需求。适配器的工作就是将这些有限的方法适配成客户端所期望的更丰富的接口。

可插入适配器的实现方式

可插入适配器有以下几种实现方式:

  1. 对象适配器模式(Object Adapter):适配器持有Adaptee实例的引用。
  2. 类适配器模式(Class Adapter):适配器通过多重继承同时继承目标接口和Adaptee。
  3. 双适配器模式(Two-Way Adapter):适配器可以同时作为Adaptee和Target接口的适配器。

下面分别介绍这三种实现方式,并给出UML图和C++代码示例。

1. 对象适配器模式(Object Adapter)

UML 类图
复制代码
+-------------------+           +-------------------+
|      Target       |           |      Adapter      |
|-------------------|           |-------------------|
| + request()       |<----------|>+ request()       |
+-------------------+           |-------------------|
                                  | - adaptee: Adaptee|
                                  |-------------------|
                                  | + request()       |
                                  |-------------------|
                                  | + doSomething()   |
                                  +-------------------+
                                        |
                                        |
                                        V
                                  +-------------------+
                                  |      Adaptee      |
                                  |-------------------|
                                  | + doSomething()   |
                                  +-------------------+
C++ 代码示例
cpp 复制代码
#include <iostream>

// Target 接口
class Target {
public:
    virtual void request() const = 0;
};

// Adaptee 类
class Adaptee {
public:
    void doSomething() const {
        std::cout << "Adaptee: Doing something." << std::endl;
    }
};

// Adapter 类
class Adapter : public Target {
private:
    Adaptee* adaptee;

public:
    Adapter(Adaptee* adaptee) : adaptee(adaptee) {}

    void request() const override {
        adaptee->doSomething();
    }
};

// 客户端代码
int main() {
    Adaptee* adaptee = new Adaptee();
    Target* adapter = new Adapter(adaptee);

    adapter->request(); // 调用适配器的方法

    delete adaptee;
    delete adapter;

    return 0;
}

2. 类适配器模式(Class Adapter)

UML 类图
复制代码
+-------------------+           +-------------------+
|      Target       |           |      Adapter      |
|-------------------|           |-------------------|
| + request()       |<----------|>+ request()       |
+-------------------+           |-------------------|
                                  | + doSomething()   |
                                  |-------------------|
                                  +-------------------+
                                        ^
                                        |
                                        |
                                  +-------------------+
                                  |      Adaptee      |
                                  |-------------------|
                                  | + doSomething()   |
                                  +-------------------+
C++ 代码示例
cpp 复制代码
#include <iostream>

// Target 接口
class Target {
public:
    virtual void request() const = 0;
};

// Adaptee 类
class Adaptee {
public:
    void doSomething() const {
        std::cout << "Adaptee: Doing something." << std::endl;
    }
};

// Adapter 类
class Adapter : public Target, private Adaptee {
public:
    void request() const override {
        doSomething();
    }
};

// 客户端代码
int main() {
    Target* adapter = new Adapter();

    adapter->request(); // 调用适配器的方法

    delete adapter;

    return 0;
}

3. 双适配器模式(Two-Way Adapter)

UML 类图
复制代码
+-------------------+           +-------------------+
|      Target       |           |      Adapter      |
|-------------------|           |-------------------|
| + request()       |<----------|>+ request()       |
+-------------------+           |-------------------|
                                  | + doSomething()   |
                                  |-------------------|
                                  +-------------------+
                                        ^
                                        |
                                        |
                                  +-------------------+
                                  |      Adaptee      |
                                  |-------------------|
                                  | + doSomething()   |
                                  +-------------------+
C++ 代码示例
cpp 复制代码
#include <iostream>

// Target 接口
class Target {
public:
    virtual void request() const = 0;
};

// Adaptee 接口
class Adaptee {
public:
    virtual void doSomething() const = 0;
};

// 具体的 Adaptee 类
class ConcreteAdaptee : public Adaptee {
public:
    void doSomething() const override {
        std::cout << "ConcreteAdaptee: Doing something." << std::endl;
    }
};

// Adapter 类
class Adapter : public Target, public Adaptee {
private:
    ConcreteAdaptee* adaptee;

public:
    Adapter(ConcreteAdaptee* adaptee) : adaptee(adaptee) {}

    void request() const override {
        adaptee->doSomething();
    }

    void doSomething() const override {
        adaptee->doSomething();
    }
};

// 客户端代码
int main() {
    ConcreteAdaptee* adaptee = new ConcreteAdaptee();
    Adapter* adapter = new Adapter(adaptee);

    adapter->request(); // 调用适配器的方法
    adapter->doSomething(); // 调用 Adaptee 的方法

    delete adaptee;
    delete adapter;

    return 0;
}

总结

可插入适配器和Adaptee的窄接口是适配器模式的两个重要概念。通过对象适配器、类适配器和双适配器这三种实现方式,适配器可以灵活地适配不同的Adaptee对象,解决接口不兼容的问题。这些实现方式各有优缺点,选择哪种方式取决于具体的需求和设计考虑。

在窄接口实现中,可以通过抽象实现、使用代理对象和参数化适配器方式来实现适配器模式。下面分别说明这三种方式,并给出相应的UML图和C++代码示例。

1. 抽象实现(Abstract Implementation)

抽象实现通过定义一个抽象基类来提供Adaptee的窄接口,然后具体的Adaptee实现类从这个抽象基类继承。适配器类可以持有这个抽象基类的引用,从而在运行时适配不同的具体实现。

UML 类图
复制代码
+-------------------+           +-------------------+           +-------------------+
|      Target       |           |      Adapter      |           |      Adaptee1     |
|-------------------|           |-------------------|           |-------------------|
| + request()       |<----------|>+ request()       |<----------|>+ doSomething()   |
+-------------------+           |-------------------|           +-------------------+
                                  | - adaptee: Adaptee|
                                  |-------------------|
                                  +-------------------+
                                        ^
                                        |
                                        |
                                  +-------------------+           +-------------------+
                                  |  AbstractAdaptee  |           |      Adaptee2     |
                                  |-------------------|           |-------------------|
                                  | + doSomething()   |<----------|>+ doSomething()   |
                                  +-------------------+           +-------------------+
C++ 代码示例
cpp 复制代码
#include <iostream>

// Target 接口
class Target {
public:
    virtual void request() const = 0;
};

// 抽象的 Adaptee 基类
class AbstractAdaptee {
public:
    virtual void doSomething() const = 0;
};

// 具体的 Adaptee 实现类 1
class Adaptee1 : public AbstractAdaptee {
public:
    void doSomething() const override {
        std::cout << "Adaptee1: Doing something." << std::endl;
    }
};

// 具体的 Adaptee 实现类 2
class Adaptee2 : public AbstractAdaptee {
public:
    void doSomething() const override {
        std::cout << "Adaptee2: Doing something." << std::endl;
    }
};

// Adapter 类
class Adapter : public Target {
private:
    AbstractAdaptee* adaptee;

public:
    Adapter(AbstractAdaptee* adaptee) : adaptee(adaptee) {}

    void request() const override {
        adaptee->doSomething();
    }
};

// 客户端代码
int main() {
    AbstractAdaptee* adaptee1 = new Adaptee1();
    AbstractAdaptee* adaptee2 = new Adaptee2();

    Target* adapter1 = new Adapter(adaptee1);
    Target* adapter2 = new Adapter(adaptee2);

    adapter1->request(); // 调用适配器的方法
    adapter2->request(); // 调用适配器的方法

    delete adaptee1;
    delete adaptee2;
    delete adapter1;
    delete adapter2;

    return 0;
}

2. 使用代理对象(Proxy Object)

代理对象是通过创建一个代理类来间接访问Adaptee的方法。适配器类持有这个代理对象的引用,并通过代理对象来调用Adaptee的方法。这种方式可以提供额外的控制和功能,比如访问控制、缓存等。

UML 类图
复制代码
+-------------------+           +-------------------+           +-------------------+
|      Target       |           |      Adapter      |           |      Proxy        |
|-------------------|           |-------------------|           |-------------------|
| + request()       |<----------|>+ request()       |<----------|>+ doSomething()   |
+-------------------+           |-------------------|           +-------------------+
                                  | - proxy: Proxy    |
                                  |-------------------|
                                  +-------------------+
                                        ^
                                        |
                                        |
                                  +-------------------+           +-------------------+
                                  |      Proxy        |           |      Adaptee      |
                                  |-------------------|           |-------------------|
                                  | + doSomething()   |<----------|>+ doSomething()   |
                                  +-------------------+           +-------------------+
C++ 代码示例
cpp 复制代码
#include <iostream>

// Target 接口
class Target {
public:
    virtual void request() const = 0;
};

// Adaptee 类
class Adaptee {
public:
    void doSomething() const {
        std::cout << "Adaptee: Doing something." << std::endl;
    }
};

// Proxy 类
class Proxy {
private:
    Adaptee* adaptee;

public:
    Proxy(Adaptee* adaptee) : adaptee(adaptee) {}

    void doSomething() const {
        std::cout << "Proxy: Before calling Adaptee." << std::endl;
        adaptee->doSomething();
        std::cout << "Proxy: After calling Adaptee." << std::endl;
    }
};

// Adapter 类
class Adapter : public Target {
private:
    Proxy* proxy;

public:
    Adapter(Proxy* proxy) : proxy(proxy) {}

    void request() const override {
        proxy->doSomething();
    }
};

// 客户端代码
int main() {
    Adaptee* adaptee = new Adaptee();
    Proxy* proxy = new Proxy(adaptee);
    Target* adapter = new Adapter(proxy);

    adapter->request(); // 调用适配器的方法

    delete adaptee;
    delete proxy;
    delete adapter;

    return 0;
}

3. 参数化适配器(Parameterized Adapter)

参数化适配器通过将Adaptee的方法参数化,使得适配器可以在运行时传递不同的参数来调用Adaptee的方法。这种方式可以增强适配器的灵活性。

UML 类图
复制代码
+-------------------+           +-------------------+
|      Target       |           |      Adapter      |
|-------------------|           |-------------------|
| + request()       |<----------|>+ request()       |
+-------------------+           |-------------------|
                                  | - adaptee: Adaptee|
                                  |-------------------|
                                  +-------------------+
                                        ^
                                        |
                                        |
                                  +-------------------+
                                  |      Adaptee      |
                                  |-------------------|
                                  | + doSomething(int)|
                                  +-------------------+
C++ 代码示例
cpp 复制代码
#include <iostream>

// Target 接口
class Target {
public:
    virtual void request() const = 0;
};

// Adaptee 类
class Adaptee {
public:
    void doSomething(int param) const {
        std::cout << "Adaptee: Doing something with parameter " << param << "." << std::endl;
    }
};

// Adapter 类
class Adapter : public Target {
private:
    Adaptee* adaptee;
    int param;

public:
    Adapter(Adaptee* adaptee, int param) : adaptee(adaptee), param(param) {}

    void request() const override {
        adaptee->doSomething(param);
    }
};

// 客户端代码
int main() {
    Adaptee* adaptee = new Adaptee();
    Target* adapter = new Adapter(adaptee, 42);

    adapter->request(); // 调用适配器的方法

    delete adaptee;
    delete adapter;

    return 0;
}

总结

这三种方式都可以在窄接口实现中使用,根据具体的需求选择不同的实现方式。抽象实现提供了灵活的适配能力,代理对象提供了额外的控制和功能,参数化适配器增强了适配器的灵活性。每种方式都有其适用的场景,选择合适的方式可以提高代码的可维护性和扩展性。

相关推荐
白帽攻防录44 分钟前
SRC 挖洞:PostScript 打印机驱动双 RCE,打印服务器怎么变成内网跳板
开发语言·网络安全·php·内网安全
十年Java程序媛1 小时前
Java枚举Enum完整教程|替代静态常量,开发与面试要点
java·开发语言·spring boot·后端·面试
2603_965148111 小时前
电商选品调研:通过关键词搜索API获取市场热销商品,结合商品详情API分析竞品卖点与定价
开发语言·数据库·人工智能·python·信息可视化
所以遗憾是什么呢?2 小时前
【题解】Educational Codeforces Round 195 (Rated for Div. 2) ABCDE
c++·动态规划·acm·icpc·ccpc·xcpc·codeforecs
xixiaoyunya2 小时前
Python 异步编程入门:用 asyncio 轻松实现并发任务
开发语言·python·php
学逆向的2 小时前
C 循环结构的执行效率分析
c语言·开发语言·数据结构·网络安全
小坏讲微服务3 小时前
刚发布一个月的JDK 27,为什么我建议你立刻升级?
java·开发语言·spring boot·spring·架构·求职招聘·springboot4
Lhan.zzZ4 小时前
Qt WebEngineView 在 Linux 上无法加载网页:从“看不见 HTML“到“禁用沙箱“
linux·c++·qt
打工仔折腾 AI4 小时前
用 Dashlet 把极空间 NAS 服务入口整理成统一导航首页的实践
java·开发语言·人工智能·后端·python·rpc·ai agent 实战
MATLAB代码顾问5 小时前
Simulink PI 参数扫描与批量仿真完整 MATLAB 代码
开发语言·matlab