一.适配器模式
1.原理
适配器模式的原理是将一个类的接口转换成客户希望的另一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的类可以协同工作。适配器模式有两种主要的实现方式:
2.适用场景
适配器模式可以帮助系统解决接口不兼容的问题,同时也可以提高代码的复用性和可维护性,使得系统更加灵活和可扩展。适配器模式主要应用于以下场景:
- 当需要使用一个已经存在的类,但是该类的接口与系统要求的接口不一致时,可以使用适配器模式将该类的接口转换成系统要求的接口。
- 当需要复用一些现有的类,但是这些类的接口与需要复用的类不一致时,可以使用适配器模式将这些类的接口转换成需要复用的类的接口。
- 当在设计新系统时,需要将一些已有的类集成进来,但是这些类的接口与系统的接口不兼容时,可以使用适配器模式将这些类的接口转换成系统的接口。
- 当需要为一个类提供多个不同的接口时,可以使用适配器模式将这些接口转换成该类的接口。
- 当需要实现一个复杂的功能,但是需要用到多个不同的类时,可以使用适配器模式将这些类的接口统一起来,以便于实现复杂的功能。
3.代理、桥接、装饰器、适配器区别
- 代理模式:代理模式在不改变原始类接口的条件下,为原始类定义一个代理类,主要目的是控制访问,而非加强功能,这是它跟装饰器模式最大的不同。
- 桥接模式:桥接模式的目的是将接口部分和实现部分分离,而让它们可以较为容易、独立地加以改变。
- 装饰器模式:装饰器模式在不改变原始类接口的情况下,对原始类功能进行增强,并且支持多个装饰器的嵌套使用。
- 适配器模式:适配器模式是一种时候的补救策略,适配器提供跟原始类不同的接口,而代理模式、装饰器模式提供的都是跟原来类相同的接口。
4.分类(类适配器模式、对象适配器模式)
- 类适配器模式:使用多重继承的方式,将被适配类的接口转换成目标接口。类适配器模式适用于以下场景:
1. | 需要使用一个已经存在的类,并且该类的接口与需要的接口不兼容。 |
2. | 不能修改被适配类的代码,因为该类已经被广泛使用,或者该类的源代码不可用。 |
3. | 适配器需要支持被适配类的所有接口。 |
- 对象适配器模式:使用组合的方式,将适配器类与被适配类组合在一起,实现接口适配。对象适配器模式适用于以下场景:
1. | 需要使用一个已经存在的类,并且该类的接口与需要的接口不兼容。 |
2. | 可以修改被适配类的代码,或者可以使用继承来扩展被适配类的功能。 |
3. | 适配器只需要支持被适配类的部分接口,或者需要支持多个被适配类的接口。 |
总的来说,如果可以修改被适配类的代码,并且不需要支持所有的被适配类接口,那么对象适配器模式是一个更加灵活和可扩展的选择。但是如果不能修改被适配类的代码,并且需要支持所有的被适配类接口,那么类适配器模式是一个更加合适的选择。
二.C++程序示例
1.类适配器
#include <iostream>
// 客户端需要使用的目标接口
class TargetInterface {
public:
virtual void request() = 0;
};
// 需要被适配的类
class Adaptee {
public:
void specificRequest() {
std::cout << "Adaptee::specificRequest()" << std::endl;
}
};
// 类适配器类,同时继承了目标接口和适配者类
class ClassAdapter : public TargetInterface, public Adaptee {
public:
void request() override {
specificRequest(); // 调用适配者类的方法
}
};
int main() {
TargetInterface* target = new ClassAdapter(); // 创建适配器对象
target->request(); // 调用目标接口方法
delete target;
return 0;
}
上述代码中,客户端需要使用的是目标接口 TargetInterface,但是已有的类 Adaptee的接口与之不兼容。为了解决这个问题,创建了一个类适配器ClassAdapter,它同时继承了目标接口和适配者类,同时实现了目标接口中的方法,在该方法中调用了适配者类中的方法specificRequest()。
2.对象适配器
#include <iostream>
// 客户端需要使用的目标接口
class TargetInterface {
public:
virtual void request() = 0;
};
// 需要被适配的类
class Adaptee {
public:
void specificRequest() {
std::cout << "Adaptee::specificRequest()" << std::endl;
}
};
// 对象适配器类,同时持有一个适配者类的对象
class ObjectAdapter : public TargetInterface {
private:
Adaptee* adaptee_; // 持有一个适配者类的对象
public:
ObjectAdapter(Adaptee* adaptee) : adaptee_(adaptee) {}
void request() override {
adaptee_->specificRequest(); // 调用适配者类的方法
}
};
int main() {
Adaptee* adaptee = new Adaptee(); // 创建适配者对象
TargetInterface* target = new ObjectAdapter(adaptee); // 创建适配器对象
target->request(); // 调用目标接口方法
delete target;
delete adaptee;
return 0;
}
上述代码中,Adaptee是需要被适配的类,它有一个specificRequest()方法。TargetInterface是客户端需要使用的目标接口,它有一个request()方法。ObjectAdapter是适配器类,它继承自TargetInterface,并持有一个Adaptee对象的指针。在ObjectAdapter的request()方法中,调用了Adaptee的specificRequest()方法,从而实现了将Adaptee的接口适配成TargetInterface的接口。