0117_适配器模式(Adapter)
适配器模式(Adapter Pattern)
意图
将一个类的接口转换成客户端期望的另一个接口。适配器让那些接口不兼容的类可以一起工作。
UML 图

优点
- 解耦性好:将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,而无需修改原有代码
- 提高了类的复用性:可以让多个不相关的类协同工作,提高了现有类的复用性
- 灵活性和扩展性好:通过使用适配器,可以很容易地增加新的适配器来适配新的接口
- 符合开闭原则:可以在不修改现有代码的情况下引入新的适配器类
缺点
- 增加了系统复杂性:需要增加新的接口和类,在一定程度上增加了系统的复杂度
- 过多使用会使系统混乱:如果在一个系统中过多地使用适配器,会让系统变得非常凌乱,不容易整体把握
- 可能降低执行效率:由于增加了额外的调用层次,可能会稍微降低系统的执行效率
代码示例
以下是一个适配器模式示例,人类有走路的能力,机器人也有行走的能力,但是残疾人没有,使用适配器模式为残疾人提供行走能力。
1. 目标接口 (Target Interface)
// 人类接口,人类都具有走路的能力
public interface Human {
/**
* 走路能力
*/
void walk();
}
// 机器人接口
public interface Robot {
/**
* 行走能力
*/
void move();
}
2. 具体目标类 (Concrete Target)
// 正常人类的实现
public class NormalHuman implements Human {
private String name;
public NormalHuman() {
this.name = "正常人";
}
public NormalHuman(String name) {
this.name = name;
}
@Override
public void walk() {
System.out.println(name + "正在走路");
}
}
// 机器人的实现
public class RobotImpl implements Robot {
private String model;
public RobotImpl() {
this.model = "标准机器人";
}
public RobotImpl(String model) {
this.model = model;
}
@Override
public void move() {
System.out.println(model + "正在行走");
}
public String getModel() {
return model;
}
}
3. 被适配者 (Adaptee)
// 残疾人实现类,不具备正常的行走能力
public class DisabledHuman implements Human {
/**
* 残疾人姓名
*/
private String name;
/**
* 残疾类型,比如:下肢残疾
*/
private String disabilityType;
/**
* 无参构造函数
* 默认姓名为"残疾人",残疾类型为"未知"
*/
public DisabledHuman() {
this.name = "残疾人";
this.disabilityType = "未知";
}
/**
* 有参构造函数
* @param name 姓名
* @param disabilityType 残疾类型
*/
public DisabledHuman(String name, String disabilityType) {
this.name = name;
this.disabilityType = disabilityType;
}
/**
* 实现行走方法
* 由于是残疾人,无法正常行走,会输出相应的提示信息
*/
@Override
public void walk() {
System.out.println(name + "(" + disabilityType + ")无法正常走路");
}
/**
* 获取残疾类型
* @return 残疾类型
*/
public String getDisabilityType() {
return disabilityType;
}
}
4. 适配器 (Adapter)
// 适配器类,让残疾人适配机器人的行走能力
public class WalkingAdapter implements Human {
private Robot robot;
private String adapterName;
public WalkingAdapter(Robot robot) {
this(robot, "行走适配器");
}
public WalkingAdapter(Robot robot, String adapterName) {
if (robot == null) {
throw new IllegalArgumentException("机器人对象不能为空");
}
this.robot = robot;
this.adapterName = adapterName;
}
@Override
public void walk() {
System.out.println("通过" + adapterName + ",使用机器人的行走能力:");
robot.move();
}
}
5. 客户端代码 (Client Code)
public class AdapterTest {
public static void main(String[] args) {
System.out.println("=== 适配器模式演示 ===\n");
// 正常人走路
demonstrateNormalHuman();
// 残疾人尝试走路
demonstrateDisabledHuman();
// 使用适配器让残疾人具备行走能力
demonstrateAdaptedWalking();
// 演示不同类型的适配
demonstrateDifferentAdapters();
}
private static void demonstrateNormalHuman() {
System.out.println("1. 正常人行走:");
Human normalHuman = new NormalHuman("张三");
normalHuman.walk();
System.out.println();
}
private static void demonstrateDisabledHuman() {
System.out.println("2. 残疾人尝试行走:");
Human disabledHuman = new DisabledHuman("李四", "下肢残疾");
disabledHuman.walk();
System.out.println();
}
private static void demonstrateAdaptedWalking() {
System.out.println("3. 使用适配器辅助行走:");
Robot robot = new RobotImpl("助行机器人");
Human adaptedHuman = new WalkingAdapter(robot, "智能助行器");
adaptedHuman.walk();
System.out.println();
}
private static void demonstrateDifferentAdapters() {
System.out.println("4. 不同类型的适配器:");
Robot advancedRobot = new RobotImpl("高级仿生机器人");
Human adaptedHuman = new WalkingAdapter(advancedRobot, "高级仿生助行器");
adaptedHuman.walk();
System.out.println();
}
}
在Spring框架中的应用
适配器模式在Spring框架中有广泛的应用:
-
Spring MVC中的HandlerAdapter
// Spring使用HandlerAdapter来适配不同类型的处理器(Controller) public interface HandlerAdapter { boolean supports(Object handler); ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception; // ... } // 具体的适配器实现 public class SimpleControllerHandlerAdapter implements HandlerAdapter { public boolean supports(Object handler) { return (handler instanceof Controller); } public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return ((Controller) handler).handleRequest(request, response); } } public class RequestMappingHandlerAdapter implements HandlerAdapter { // 适配@RequestMapping注解的控制器方法 } -
Spring AOP中的AdvisorAdapter
// 将不同类型的Advice适配到统一的接口 public interface AdvisorAdapter { boolean supportsAdvice(Advice advice); MethodInterceptor getInterceptor(Advisor advisor); } -
Spring Security中的AuthenticationProvider
// 适配不同的认证机制 public interface AuthenticationProvider { Authentication authenticate(Authentication authentication) throws AuthenticationException; boolean supports(Class<?> authentication); } -
Spring JDBC中的RowMapper
// 将ResultSet适配到Java对象 public interface RowMapper<T> { T mapRow(ResultSet rs, int rowNum) throws SQLException; } -
Spring中的事件监听器适配器
// 将不同的事件监听方法适配到统一的接口 public class ApplicationListenerMethodAdapter implements ApplicationListener<ApplicationEvent> { public void onApplicationEvent(ApplicationEvent event) { // 将事件适配到具体的方法调用 } }
总结
适配器模式是一种结构型模式,它充当两个不兼容接口之间的桥梁。通过定义一个适配器类,它将一个类的接口转换成客户端所期望的另一种接口,从而使原本由于接口不兼容而不能一起工作的类可以一起工作。
核心思想:转换接口,兼容协作
- 对象适配器(推荐):使用组合,更灵活,可以适配多个不同的被适配者
- 类适配器:使用继承,在某些语言中更简洁,但Java中受限于单继承
在Spring框架中,适配器模式被大量用于集成各种不同的组件和技术,提供了极大的灵活性和扩展性。

浙公网安备 33010602011771号