「这是我参与2022首次更文挑战的第2天,活动详情查看:2022首次更文挑战」。
1.模式动机
- 客户端需要调用一个接口,现有的类中可以满足客户端的这项服务,但是现有的类所提供的的接口并不是客户端所需要的,因此就需要将其转换以达到重用的目的,这个转换可以通过适配器模式完成。
- 在适配器模式中可以定义一个包装类,这个包装类可以包装不兼容的接口,包装类是适配器,被包装的类是适配者。
- 客户调用适配器中的方法时,适配器调用的其实是适配者中的方法,但是这个过程客户并不知道,客户也无需访问适配者。
2.模式定义
将一个接口转换成客户希望的另一个的接口,适配器模式使接口不兼容的那些类可以一起工作。
3.模式结构
适配器模式有类适配器和对象适配器两种实现方式,有四个角色:
- 目标抽象类:Target
- 适配器:Adapter
- 适配者:Adaptee
- 客户:Client
4.时序图
5.代码分析
代码案例:买手机时都会附赠一个充电器,生活中使用的电源是220V,手机支持的充电电压是5V,所以买手机时所带的充电器就充当了适配器的角色,将220V的电压转换成5V
- 类适配器实现
/**
* 目标抽象类
*/
public interface Target {
void convert_5V();
}
/**
* 适配者:标准电压
*/
public static class PowerPort220V {
public void output220V() {
System.out.println("输出220V电压");
}
}
/**
* 适配器:充电器的适配器
*/
public static class ConvertAdapter extends PowerPort220V implements Target {
@Override
public void convert_5V() {
this.output220V();
}
}
/**
* 具体使用
*/
public static void main(String[] args) {
//类适配器实现方式
Target target = new ConvertAdapter();
target.convert_5V();
}
- 对象适配器实现
/**
* 目标抽象类
*/
public interface Target {
void convert_5V();
}
/**
* 适配者:标准电压
*/
public static class PowerPort220V {
public void output220V() {
System.out.println("输出220V电压");
}
}
/**
* 适配器:充电器的适配器
*/
public static class ConvertAdapter implements Target {
PowerPort220V powerPort220V;
public ConvertAdapter(PowerPort220V powerPort220V) {
this.powerPort220V = powerPort220V;
}
@Override
public void convert_5V() {
powerPort220V.output220V();
}
}
/**
* 具体使用
*/
public static void main(String[] args) {
//对象适配器
PowerPort220V powerPort220V = new PowerPort220V();
Target target = new ConvertAdapter(powerPort220V);
target.convert_5V();
}
6.优点
- 解耦目标类和适配者类,引入了适配器类并将适配者类在适配器类中重用且无需修改原有代码
- 有良好的的透明性和复用性,对于客户端来讲它并不知道适配器类中调用的是适配者的方法同时这样也实现了复用
- 灵活性和可扩展性很好,通过配置文件就可以更换适配器也可以在不修改原有代码的基础上增加新的适配器,符合【开闭原则】
- 类适配器模式: 由于适配器类是适配者类的子类,因此可以在适配器类中置换一些适配者的方法,使得适配器的灵活性更强。
- 对象适配器模式: 一个对象适配器可以把多个不同的适配者适配到同一个目标,也就是说,同一个适配器可以把适配者类和它的子类都适配到目标接口。
7.缺点
- 类适配器模式: Java不支持多重继承的语言,一次最多只能适配一个适配者类,而且目标抽象类只能为抽象类,不能为具体类,其使用有一定的局限性,不能将一个适配者类和它的子类都适配到目标接口。
- 对象适配器模式: 与类适配器模式相比,要想置换适配者类的方法就不容易。如果一定要置换掉适配者类的一个或多个方法,就只好先做一个适配者类的子类,将适配者类的方法置换掉,然后再把适配者类的子类当做真正的适配者进行适配,实现过程较为复杂。
8.适用环境
- 系统需要使用现有的类,而这些类的接口不符合系统的需要。
- 想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。
9.模式扩展
当不需要全部实现接口提供的方法时,可先设计一个抽象类实现接口,并为该接口中每个方法提供一个默认实现(空方法),那么该抽象类的子类可有选择地覆盖父类的某些方法来实现需求,它适用于一个接口不想使用其所有的方法的情况。因此也称为单接口适配器模式。
参考链接:适配器模式