适配器模式

一、【简介】什么是适配器模式

        适配器模式Adapter 是⼀种结构型设计模式,它可以将⼀个类的接⼝转换成客户希望的另⼀个接⼝,主要⽬的是充当两个不同接⼝之间的桥梁,使得原本接⼝不兼容的类能够⼀起⼯作。

二、【基本结构】

适配器模式分为以下⼏个基本⻆⾊:

⽬标接⼝Target : 客户端希望使⽤的接⼝
适配器类Adapter : 实现客户端使⽤的⽬标接⼝,持有⼀个需要适配的类实例。
被适配者Adaptee : 需要被适配的类
        (可以把适配器模式理解成拓展坞,起到转接的作⽤,原有的接⼝是USB,但是客户端需要使⽤type-c , 便使⽤拓展坞提供⼀个type-c 接⼝给客户端使⽤)        

        这样,客户端就可以使⽤⽬标接⼝,⽽不需要对原来的Adaptee 进⾏修改, Adapter 起到⼀个转接扩展的作⽤。

三、【应用场景】

        在开发过程中,适配器模式往往扮演者“补救”和“扩展”的⻆⾊:

当使⽤⼀个已经存在的类,但是它的接⼝与你的代码不兼容时,可以使⽤适配器模式。
在系统扩展阶段需要增加新的类时,并且类的接⼝和系统现有的类不⼀致时,可以使⽤适配器模式。
·      使⽤适配器模式可以将客户端代码与具体的类解耦,客户端不需要知道被适配者的细节,客户端代码也不需要修改,这使得它具有良好的扩展性,但是这也势必导致系统变得更加复杂。
       具体来说,适配器模式有着以下应⽤:

不同的项⽬和库可能使⽤不同的⽇志框架,不同的⽇志框架提供的API也不同,因此引⼊了适配器模式使得不同的API适配为统⼀接⼝。
Spring MVC中, HandlerAdapter 接⼝是适配器模式的⼀种应⽤。它负责将处理器(Handler)适配到框架中,使得不同类型的处理器能够统⼀处理请求。
在.NET 中, DataAdapter ⽤于在数据源(如数据库)和 DataSet 之间建⽴适配器,将数据从数据源适配到 DataSet 中,以便在.NET应⽤程序中使⽤。

四、

适配器模式(Adapter Pattern)是一种软件设计模式,它能使接口不兼容的两个类可以协同工作。适配器模式包含类适配器 对象适配器两种形式。

类适配器通过多重继承实现,对象适配器通过组合实现。

以下是类适配器示例代码:

// 目标接口
class Target {
public:
    virtual void Request() = 0;
    virtual ~Target() {}
};
 
// 已存在的接口
class Adaptee {
public:
    void SpecificRequest() {
        std::cout << "Adaptee SpecificRequest." << std::endl;
    }
};
 
// 类适配器
class Adapter : public Target, private Adaptee {
public:
    void Request() override {
        this->SpecificRequest();
    }
};
 
int main() {
    Target* adapter = new Adapter();
    adapter->Request();
    delete adapter;
    return 0;
}

对象适配器示例代码:

// 目标接口
class Target {
public:
    virtual void Request() = 0;
    virtual ~Target() {}
};
 
// 已存在的接口
class Adaptee {
public:
    void SpecificRequest() {
        std::cout << "Adaptee SpecificRequest." << std::endl;
    }
};
 
// 对象适配器
class Adapter : public Target {
private:
    Adaptee* adaptee;
public:
    Adapter() {
        adaptee = new Adaptee();
    }
    ~Adapter() {
        delete adaptee;
    }
    void Request() override {
        adaptee->SpecificRequest();
    }
};
 
int main() {
    Target* adapter = new Adapter();
    adapter->Request();
    delete adapter;
    return 0;
}

在这两个示例中,Adapter类都将Adaptee的接口转换成Target接口,使得客户端可以通过Target接口调用Adaptee的方法。类适配器通过多重继承实现,而对象适配器通过组合实现。

五、示例

5.1 题目描述
    小明购买了一台新电脑,该电脑使用 TypeC 接口,他已经有了一个USB接口的充电器和数据线,为了确保新电脑可以使用现有的USB接口充电器和数据线,他购买了一个TypeC到USB的扩展坞。请你使用适配器模式设计并实现这个扩展坞系统,确保小明的新电脑既可以通过扩展坞使用现有的USB接口充电线和数据线,也可以使用TypeC接口充电。


题目包含多行输入,第一行输入一个数字 N (1 < N <= 20),表示后面有N组测试数据。
之后N行都是一个整数,1表示使用电脑本身的TypeC接口,2表示使用扩展坞的USB接口充电。
    
 方法一为普通的直接调用;
 方法二为通过适配器类(TypeCAdapter)去调用被适配(TypeC)来转换为原有的目标对象(Usb),这样就完成了适配器模式的核心思想:搭建桥梁。

/**
* @version Copyright (c) 
* @file AdapterMode.hpp
* @brief 适配器模式
*/
 
#include<iostream>
#include<string>
 
using namespace std;
 
// 原有的USB类 -- 目标接口
class Usb
{
public:
    virtual void ChargeWithUsb() = 0; 
};
 
// Typec类 -- 被适配者类(TypeC接口:适配后,TypeC接口可以使用USB接口)
class TypeC
{
public:
    virtual void ChargeWithTypeC() = 0;
};
 
// 适配器类  通过持有 被适配者类的实例及方法 来完成桥梁搭建
class TypeCAdapter : public Usb
{
    // 持有一个 (被适配者)TypeC的类的实例
private:
    TypeC * _typeC;
    
    // 构造函数
public:
    TypeCAdapter(TypeC * typeC)
	{
        this->_typeC = typeC;
    }
    //重载USB接口函数 -- 利用USB充电  
    void ChargeWithUsb() override
	{
        // 调用被适配者类的方法 -- 利用TypeC充电
        _typeC->ChargeWithTypeC();
    }
};
 
// 新电脑 -- 使用 TypeC 接口
class NewComputer : public TypeC // Typec类 -- 被适配者类
{
public:
    // 重载TypeC的充电函数
    void ChargeWithTypeC() override {
        std::cout << "TypeC" << endl;
    }
};
 
// USB适配器的充电器
class UsbAdapterCharge : public Usb // 原有的USB类
{
public:
    void ChargeWithUsb() override{
        std::cout << "USB Adapter" << endl;
    }
};
 
// 【方法一】:这种方法没用到适配器类的桥梁作用
// int main()
// {
//     // 测试组数
//     int testNum = 0;
//     std::cin >> testNum;//第一行输入一个数字 N (1 < N <= 20),表示后面有N组测试数据
    
//     for(int i = 0; i < testNum; i++)
//     {
//         int choice = 0;
//         std::cin >> choice;
//         if(choice == 1) //1表示使用电脑本身的TypeC接口
//         {
//             NewComputer *newComputer = new NewComputer();
//             newComputer->ChargeWithTypeC();//用电脑本身的TypeC接口
            
//             delete newComputer;
//             newComputer = nullptr;
//         }
//         else if(choice == 2) //2表示使用扩展坞的USB接口充电
//         {
//             UsbAdapterCharge *usbAdapter = new UsbAdapterCharge();
//             usbAdapter->ChargeWithUsb();//用扩展坞的USB接口充电
            
//             delete usbAdapter;
//             usbAdapter = nullptr;
//         }
//         else continue;
//     }
 
//     return 0;
// }
 
// 【方法二】: 利用适配器来进行被适配者类的调用
int main()
{
    // 测试组数
    int testNum = 0;
    std::cin >> testNum;//第一行输入一个数字 N (1 < N <= 20),表示后面有N组测试数据
    
    for(int i = 0; i < testNum; i++)
    {
        int choice = 0;
        std::cin >> choice;
        if(choice == 1)//1表示使用电脑本身的TypeC接口。经过适配器,可以使用USB接口
        {
            // 均为 统一的原有接口 USB
			//适配器模式:父类指针us指向子类TypeCAdapter对象!!
			// 使用特殊功能类,即适配类:需要先创建一个被适配类的对象作为参数!
            Usb *usb = new TypeCAdapter(new NewComputer());
            usb->ChargeWithUsb();
            
            delete usb;
            usb = nullptr;
        }
        else if(choice == 2)//2表示使用扩展坞的USB接口充电
        {
            // 均为 统一的原有接口 USB
            Usb *usbAdapter = new UsbAdapterCharge();
            usbAdapter->ChargeWithUsb();
            
            delete usbAdapter;
            usbAdapter = nullptr;
        }
        else continue;
    }
 
    return 0;
}


原文链接:https://blog.csdn.net/K1_uestc/article/details/135497351

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值