【设计模式】适配器模式

1. 模式说明

2. 模式原理

2.1 类的适配器模式

2.2 对象的适配器模式

两种方式的优缺点


1. 模式说明

适配器模式(Adapter Pattern)是一种结构型设计模式,它允许将一个接口转换成客户端所期望的另一种接口。适配器模式的核心思想是通过创建一个中间层(适配器),使得原本由于接口不兼容而无法一起工作的类可以协同工作。

适配器模式有两种主要形式:
1. 类适配器:通过继承来实现适配。
2. 对象适配器:通过组合来实现适配,更常用且更灵活。

2. 模式原理

2.1 类的适配器模式

类的适配器模式是把适配的类的API转换成为目标类的API。

2.1.1 UML类图 & 组成

在上图中可以看出:

  • 冲突:Target期待调用Request方法,而Adaptee并没有(这就是所谓的不兼容了)。
  • 解决方案:为使Target能够使用Adaptee类里的SpecificRequest方法,故提供一个中间环节Adapter类(继承Adaptee & 实现Target接口),把Adaptee的API与Target的API衔接起来(适配)。

Adapter与Adaptee是继承关系,这决定了这个适配器模式是类的

2.1.3 实例讲解

// 目标接口   (原接口,不想修改)
class Target {
public:
    virtual void request() = 0;
};


// 被适配类   (新接口)
class Adaptee {
public:
    void specificRequest() {
        std::cout << "Adaptee specific request" << std::endl;
    }
};




新接口的名字specificRequest不一样了,不能被原代码直接调用。搞一个类适配器包裹封装(适配)出原来的接口:->request()


// 类适配器
class Adapter : public Target, public Adaptee { // 继承Target和Adaptee
public:
    void request() override {
        specificRequest(); // 调用Adaptee的方法
    }
};


通过适配器,可以用原来的调用代码target->request() 调用新功能:

int main() {
    Target* target = new Adapter();
    target->request(); // 输出: Adaptee specific request

    delete target;
    return 0;
}

main函数中,我们创建了一个Adapter对象,并通过Target指针来调用其request方法。由于Adapter实现了Target接口,并且在其request方法中调用了AdapteespecificRequest方法,所以客户端代码可以透明地使用Target接口,而不需要关心底层的Adaptee实现。

2.2 对象的适配器模式

与类的适配器模式相同,对象的适配器模式也是把适配的类的API转换成为目标类的API。
与类的适配器模式不同的是,对象的适配器模式不是使用继承关系连接到Adaptee类,而是使用委派关系连接到Adaptee类。


2.2.1 UML类图


在上图中可以看出:
• 冲突:Target期待调用Request方法,而Adaptee并没有(这就是所谓的不兼容了)。
• 解决方案:为使Target能够使用Adaptee类里的SpecificRequest方法,故提供一个中间环节Adapter类(包装了一个Adaptee的实例),把Adaptee的API与Target的API衔接起来(适配)。
Adapter与Adaptee是委派关系,这决定了适配器模式是对象的。

2.2.2 实例讲解

// 目标接口  (原接口,不想改)
class Target {
public:
    virtual void request() = 0;
};


// 被适配类  (新接口)
class Adaptee {
public:
    void specificRequest() {
        std::cout << "Adaptee specific request" << std::endl;
    }
};


创建适配器(但是不继承Target和Adaptee,而是在其中创建新接口的对象)


// 适配器类(对象适配器)
class Adapter : public Target {
public:
    Adapter(Adaptee* adaptee) : m_adaptee(adaptee) {}

    void request() override {
        m_adaptee->specificRequest();
    }

private:
    Adaptee* m_adaptee;
};


原代码中创建适配器,就可以使用原来的接口调用新功能 target->request()

int main() {
    Adaptee* adaptee = new Adaptee();
    Target* target = new Adapter(adaptee);
    target->request();
    
    delete target;
    delete adaptee;
    return 0;
}

两种方式的优缺点

3.2 类的适配器模式
优点
• 使用方便,代码简化
仅仅引入一个对象,并不需要额外的字段来引用Adaptee实例
缺点
• 高耦合,灵活性低
使用对象继承的方式,是静态的定义方式

3.3 对象的适配器模式
优点
• 灵活性高、低耦合
采用 “对象组合”的方式,是动态组合方式
缺点
• 使用复杂
需要引入对象实例
特别是需要重新定义Adaptee行为时需要重新定义Adaptee的子类,并将适配器组合适配


参考:https://www.jianshu.com/p/9d0575311214

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值