适配器模式分为类适配器(继承实现)、对象适配器(组合实现,实际项目最常用),还有接口适配器(缺省适配器)。
核心作用:将一个类的接口,转换成客户期望的另一个接口,让原本接口不兼容的类可以一起工作。
1、对象适配器(推荐,组合方式,Java 优先使用,规避单继承限制)
场景示例:现有 220V家用交流电,目标需要输出 5V 给手机充电,适配器充当充电器。
/**
* 被适配者:家用220V交流电
*/
public class Ac220V {
public int output220V() {
return 220;
}
}
/**
* 目标接口:手机需要5V电压
*/
public interface Target5V {
int output5V();
}
/**
* 对象适配器:充电器,组合持有被适配对象
*/
public class VoltageAdapter implements Target5V {
// 组合:持有被适配对象,不使用继承
private final Ac220V ac220V;
public VoltageAdapter(Ac220V ac220V) {
this.ac220V = ac220V;
}
@Override
public int output5V() {
int src = ac220V.output220V();
System.out.println("适配器转换:输入电压=" + src + "V");
int dst = src / 44; // 220 /44 =5
System.out.println("适配器输出:" + dst + "V");
return dst;
}
}
/**
* 客户端:手机
*/
public class Phone {
public void charge(Target5V target5V){
int v = target5V.output5V();
System.out.println("手机使用 "+v+"V 充电");
}
}
// 测试主类
class TestMain {
public static void main(String[] args) {
Ac220V ac220V = new Ac220V();
Target5V adapter = new VoltageAdapter(ac220V);
Phone phone = new Phone();
phone.charge(adapter);
}
}
输出:
适配器转换:输入电压=220V
适配器输出:5V
手机使用 5V 充电
2、类适配器(继承实现,Java 受单继承限制,实际很少用)
缺点:Java 只能单继承,如果被适配类已经继承其他类,就无法使用。
// 被适配者
class Ac220V2 {
public int output220V(){
return 220;
}
}
// 目标接口
interface Target5V2 {
int output5V();
}
/**
* 类适配器:直接继承被适配类,实现目标接口
*/
class VoltageClassAdapter extends Ac220V2 implements Target5V2{
@Override
public int output5V() {
int src = output220V();
return src / 44;
}
}
// 测试
class ClassAdapterTest{
public static void main(String[] args) {
Target5V2 adapter = new VoltageClassAdapter();
System.out.println(adapter.output5V());
}
}
3、接口适配器(缺省适配器模式)
当不想实现接口中全部方法,写一个抽象适配器空实现所有接口方法,子类只重写需要的方法。
// 有很多抽象方法的接口
interface ManyMethodInterface {
void func1();
void func2();
void func3();
}
/**
* 缺省适配器,空实现全部接口方法
*/
abstract class AbsAdapter implements ManyMethodInterface{
@Override
public void func1() {}
@Override
public void func2() {}
@Override
public void func3() {}
}
// 业务子类,只重写自己需要的方法
class BusinessDemo extends AbsAdapter{
@Override
public void func2() {
System.out.println("只实现func2业务逻辑");
}
}
class DefaultAdapterTest{
public static void main(String[] args) {
ManyMethodInterface demo = new BusinessDemo();
demo.func2();
}
}
4、JDK 中适配器典型例子
java.util.Arrays#asList()、SpringMVC HandlerAdapter(处理器适配器) SpringMVC HandlerAdapter 伪代码示意:
// 目标接口
public interface HandlerAdapter {
boolean supports(Object handler);
ModelAndView handle(Object handler);
}
// 多种适配器适配不同Controller实现
class HttpRequestHandlerAdapter implements HandlerAdapter{...}
class SimpleControllerHandlerAdapter implements HandlerAdapter{...}
总结
对象适配器(组合)优先使用,解耦,不受 Java 单继承约束;
类适配器依靠继承,耦合高,业务尽量避免;
接口适配器适合接口方法多,只想重写部分方法场景。
本文原创作者:易君召,详见:https://www.yijunzhao.cc/about,转载请注明出处。
原文链接
欢迎访问