浏览次数:2,471
点赞次数:0
评论次数:0
发布日期:2022-06-15
文章字数:1.4k
阅读时长:3.9分钟
死磕设计模式—适配器模式
前言(八问知识体系)
1.简介
-
什么是适配器模式?
- 1.将一个接口转换成客户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作
- 2.适配器模式既可以作为类结构型模式,也可以作为对象结构型模式
- 3.适配器模式属于结构型模式
- 4.适配器实现了统一管理,一个目标是适配接口对象多个适配器类
-
适配器模式的优缺点?
- 优点
- 1.将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,而无须修改原有代码
- 2.增加了类的透明性和复用性,将具体的实现封装在适配者类中
- 3.灵活性和扩展性都非常好,通过使用配置文件,可以很方便地更换适配器
- 4.对象适配器模式还可以将不通的适配者适配到同一个目标接口上
- 缺点
- 1.过多的使用适配器类会让程序变得复杂
- 2.类适配器模式还存在单继承的问题
- 优点
2.类图
2.1.类适配器类图
注意事项:Java是单继承机制,类适配器需要继承源类,这是一个缺点,同时源类的方法也在适配器类中暴漏出来,增加类使用的成本。
2.2.对象适配器类图
PS:对象适配器模式更多是为类解决类适配器中的单继承问题,修改类实现方式,根据合成复用原则,使用组合的方式代替继承,同时使用的成本降低。
2.3.接口适配器类图
PS:接口适配器就是重写接口中我们需要使用的方法,但是接口中会存在很多方法,所以我们会使用一个抽象类适配器采用默认空方法来实现接口,使用的时候采用内部类来覆写。
3.代码示例
3.1.类适配器
被适配类
@Slf4j
public class Adaptee {
/**
* outPut220V
*
* @return 220V电压
* @description 输出220V的电压
* @author luokangyuan
* @date 2019/11/3 16:49
* @version 1.0.0
*/
public int outPut220V() {
log.info("输出220V的电压");
return 220;
}
}
目标抽象接口
public interface Target {
/**
* outPut22V
*
* @description 输出22V的电压
* @return 22V的电压
* @author luokangyuan
* @date 2019/11/3 16:50
* @version 1.0.0
*/
int outPut22V();
}
适配器类
public class Adapter extends Adaptee implements Target {
@Override
public int outPut22V() {
// 1.得到需要适配的数据
int i = outPut220V();
// 2.适配转换操作
int result = i / 10;
// 返回适配后结果
return result;
}
}
客户端
public class Phone {
/**
* charging
*
* @param target : 适配接口
* @description 手机充电方法
* @author luokangyuan
* @date 2019/11/3 17:00
* @version 1.0.0
*/
public void charging(Target target) {
// 得到期望结果,开始后续操作
int i = target.outPut22V();
log.info("当前电压为{},开始充电操作", i);
}
}
测试调用
public static void main(String[] args) {
Phone phone = new Phone();
phone.charging(new Adapter());
}
3.2.对象适配器
由于类适配器需要继承源类,由于Java
是单继承,所以存在很大的局限性,所以出现类对象适配器,就是在适配器类中不再使用继承源类的方式,而是使用源类的实例来解决兼容性问题,即持有Src类,实现Dst类,完成适配。
根据合成复用原则,在系统中尽量使用关联关系来代替继承关系,对象适配器模式才是适配器模式中最常用的一种模式。
被适配类
public class Adaptee {
/**
* outPut220V
*
* @return 220V电压
* @description 输出220V的电压
* @author luokangyuan
* @date 2019/11/3 16:49
* @version 1.0.0
*/
public int outPut220V() {
log.info("输出220V的电压");
return 220;
}
}
目标抽象接口
public interface Target {
/**
* outPut22V
*
* @description 输出22V的电压
* @return 22V的电压
* @author luokangyuan
* @date 2019/11/3 16:50
* @version 1.0.0
*/
int outPut22V();
}
适配器类
public class Adapter implements Target {
private Adaptee adaptee;
public Adapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public int outPut22V() {
// 1.得到需要适配的数据
int i = adaptee.outPut220V();
// 2.适配转换操作
int result = i / 10;
// 返回适配后结果
return result;
}
}
客户端
public class Phone {
/**
* charging
*
* @param target : 适配接口
* @description 手机充电方法
* @author luokangyuan
* @date 2019/11/3 17:00
* @version 1.0.0
*/
public void charging(Target target) {
// 得到期望结果,开始后续操作
int i = target.outPut22V();
log.info("当前电压为{},开始充电操作", i);
}
}
测试调用
public static void main(String[] args) {
Phone phone = new Phone();
phone.charging(new Adapter(new Adaptee()));
}
3.3.接口适配器
源接口
public interface IAdaptee {
void method1();
void method2();
void method3();
void method4();
}
抽象的接口适配器类
public abstract class AbsAdapter implements IAdaptee{
@Override
public void method1() {
}
@Override
public void method2() {
}
@Override
public void method3() {
}
@Override
public void method4() {
}
}
客户端
@Slf4j
public class Client {
public static void main(String[] args) {
new AbsAdapter() {
@Override
public void method1() {
log.info("我只是使用了接口中的method1");
}
};
}
}
4.总结
-
适配器模式的使用场景?
- 1.系统需要使用现有的类,而这些类的接口不符合系统的需要
-
适配器模式的使用案例?
- 1.SpringMvc中的HandlerAdapter使用了适配器模式
- 2.java.util.Arrays#asList()也使用了适配器模式
- 3.spring AOP中的AdvisorAdapter使用了适配器模式
- 适配者类角色