适配器模式是一种常见的设计模式,它允许你将不同接口的类协调工作,使之能够协同合作。适配器模式是构造型设计模式之一,主要用于处理两个不兼容的接口之间的协调问题。在本文中,我们将深入了解适配器模式的概念、组成、应用场景以及实际示例。
1. 介绍
适配器模式是一种结构性设计模式,它可以让不兼容的接口协同工作。这种模式常用于系统需要与外部组件进行集成,但由于接口不匹配而导致无法直接协作的情况。适配器模式可以在不修改现有代码的情况下,将不同接口的类无缝连接起来,从而实现协同工作。
2. 适配器模式的组成
适配器模式主要由以下几个组成部分组成:
-
目标接口(Target Interface): 这是客户端所期望的接口,适配器将源接口适配成目标接口,使得客户端可以通过目标接口与适配器交互。
-
源接口(Adaptee Interface): 这是需要被适配的源类的接口。由于源接口与目标接口不兼容,需要通过适配器来进行适配。
-
适配器(Adapter): 适配器是一个实现了目标接口的类,它包含一个对源接口的引用。适配器的主要作用是将客户端的请求转发给源接口,从而实现对源接口的适配。
-
+-----------------------------------+ | DataProvider | +-----------------------------------+ ^ ^ | | | | +-------------------+ +------------------+ | LegacyDataProvider| | LegacyDataAdapter| +-------------------+ +------------------+ | fetchDataInLegacy | | legacyDataProvider: LegacyDataProvider +-------------------+ +------------------+
3. 类适配器和对象适配器
适配器模式可以分为两种主要类型:类适配器和对象适配器。
-
类适配器: 在类适配器中,适配器类继承了源接口类,并实现了目标接口。这样,适配器类就同时拥有了源接口和目标接口的功能。
-
对象适配器: 在对象适配器中,适配器类引用了源接口对象,并实现了目标接口。适配器类将客户端的请求委托给源接口对象来处理。
4. 适配器模式的应用场景
适配器模式适用于以下场景:
- 不同系统之间需要协同工作,但接口不兼容的情况。
- 需要重用已有类,但这些类的接口与现有代码不匹配。
- 需要在系统中增加一层适配器,以提供统一的接口,简化系统架构。
5. 适配器模式的优缺点
适配器模式的优点包括:
- 解决不兼容接口问题,提高代码复用性。
- 可以将不同的组件集成到一起,降低系统的耦合度。
适配器模式的缺点包括:
- 可能会增加代码复杂性,引入间接层。
- 在一些情况下,可能会影响系统性能。
6. 实际应用示例
示例一:将不同格式的数据转换为统一格式
考虑一个系统需要从不同数据源中获取数据,其中每个数据源的数据格式都不同。我们可以使用适配器模式将每个数据源的数据格式适配成统一的格式,以便系统能够统一处理这些数据。
示例代码:
// 目标接口
interface DataProvider {
String fetchData();
}
// 源接口
class LegacyDataProvider {
String fetchDataInLegacyFormat() {
// 返回旧格式的数据
}
}
// 适配器
class LegacyDataAdapter implements DataProvider {
private LegacyDataProvider legacyDataProvider;
public LegacyDataAdapter(LegacyDataProvider legacyDataProvider) {
this.legacyDataProvider = legacyDataProvider;
}
@Override
public String fetchData() {
String legacyData = legacyDataProvider.fetchDataInLegacyFormat();
// 将旧格式数据适配成新格式数据
return adaptLegacyData(legacyData);
}
private String adaptLegacyData(String legacyData) {
// 适配逻辑
}
}
示例二:不同类型数据库的访问
假设一个系统需要支持不同类型的数据库,但每种数据库的访问接口都不同。我们可以使用适配器模式来创建适配器,将不同数据库的访问方式适配成统一的数据库访问接口。
示例代码:
// 目标接口
interface Database {
void connect();
void query(String sql);
}
// 源接口和类
class MySQLDatabase {
void establishConnection() {
// 建立连接
}
void executeSQL(String sql) {
// 执行SQL查询
}
}
// 适配器
class MySQLDatabaseAdapter implements Database {
private MySQLDatabase mySQLDatabase;
public MySQLDatabaseAdapter(MySQLDatabase mySQLDatabase) {
this.mySQLDatabase = mySQLDatabase;
}
@Override
public void connect() {
mySQLDatabase.establishConnection();
}
@Override
public void query(String sql) {
mySQLDatabase.executeSQL(sql);
}
}
示例三:实际工程中应用举例
比如在实际工程应用中,我们期望适配不同的三方公众平台扫码登陆体系,登陆后我们期望从三方公众平台获取登陆用户的用户信息,这时就可以采用适配器模式来处理,
示例代码:
// 目标接口
public interface UserInfoQuery {
UserInfo queryUserInfoByAccessToken(String accessToken);
}
class UserInfo {
private String username;
private String email;
// 构造函数、getter和setter方法等
}
// 公众平台1的用户信息查询接口
public interface TripProfileInfoQuery {
UserProfile queryUserProfileByAccessToken(String accessToken);
}
class UserProfile {
private String name;
private String mail;
private Integer age;
// .. 其他属性
// 构造函数、getter和setter方法等
}
// 适配器
public class TripUserInfoAdapter implements UserInfoQuery {
private TripProfileInfoQuery query;
public UserInfo queryUserInfoByAccessToken(String accessToken) {
UserProfile profile = query.queryUserProfileByAccessToken(accessToken);
UserInfo info = new UserInfo();
info.setUserName(profile.getName());
info.setEmail(profile.getmail());
return info;
}
}
在当前示例中,无论三方公众平台如何修改该接口,我们仅需要修改适配器里面的内容即可,对于我们自身的业务代码无需任何修改,若直接用硬编码将三方接口写入到业务逻辑,则业务逻辑代码将严格受到三方接口变更的制约。
7. 适配器模式与其他模式的关系
-
桥接模式与适配器模式的区别: 桥接模式主要关注在抽象与实现之间的解耦,而适配器模式主要关注将不兼容的接口协同工作。
-
装饰器模式与适配器模式的对比: 装饰器模式用于动态地为对象添加新的行为,而适配器模式用于将不兼容的接口协调工作。
8. 在现实世界中的类比
适配器模式在现实世界中的应用就像电源适配器一样。电源适配器可以将不同形状的插头适配成标准插座,使得设备可以正常工作。
9. 总结与展望
适配器模式是一种重要的设计模式,它能够帮助我们解决不兼容接口的问题,实现不同类之间的协作。通过适配器模式,我们可以使现有的类能够在不修改其代码的情况下,协同工作。在实际开发中,合理使用适配器模式可以提高代码的复用性和系统的可维护性。