0117_适配器模式(Adapter)

适配器模式(Adapter Pattern)

意图

将一个类的接口转换成客户端期望的另一个接口。适配器让那些接口不兼容的类可以一起工作。

UML 图

Adapter

优点

  1. 解耦性好:将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,而无需修改原有代码
  2. 提高了类的复用性:可以让多个不相关的类协同工作,提高了现有类的复用性
  3. 灵活性和扩展性好:通过使用适配器,可以很容易地增加新的适配器来适配新的接口
  4. 符合开闭原则:可以在不修改现有代码的情况下引入新的适配器类

缺点

  1. 增加了系统复杂性:需要增加新的接口和类,在一定程度上增加了系统的复杂度
  2. 过多使用会使系统混乱:如果在一个系统中过多地使用适配器,会让系统变得非常凌乱,不容易整体把握
  3. 可能降低执行效率:由于增加了额外的调用层次,可能会稍微降低系统的执行效率

代码示例

以下是一个适配器模式示例,人类有走路的能力,机器人也有行走的能力,但是残疾人没有,使用适配器模式为残疾人提供行走能力。

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框架中有广泛的应用:

  1. 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注解的控制器方法
    }
    
  2. Spring AOP中的AdvisorAdapter

    // 将不同类型的Advice适配到统一的接口
    public interface AdvisorAdapter {
        boolean supportsAdvice(Advice advice);
        MethodInterceptor getInterceptor(Advisor advisor);
    }
    
  3. Spring Security中的AuthenticationProvider

    // 适配不同的认证机制
    public interface AuthenticationProvider {
        Authentication authenticate(Authentication authentication) throws AuthenticationException;
        boolean supports(Class<?> authentication);
    }
    
  4. Spring JDBC中的RowMapper

    // 将ResultSet适配到Java对象
    public interface RowMapper<T> {
        T mapRow(ResultSet rs, int rowNum) throws SQLException;
    }
    
  5. Spring中的事件监听器适配器

    // 将不同的事件监听方法适配到统一的接口
    public class ApplicationListenerMethodAdapter implements ApplicationListener<ApplicationEvent> {
        public void onApplicationEvent(ApplicationEvent event) {
            // 将事件适配到具体的方法调用
        }
    }
    

总结

适配器模式是一种结构型模式,它充当两个不兼容接口之间的桥梁。通过定义一个适配器类,它将一个类的接口转换成客户端所期望的另一种接口,从而使原本由于接口不兼容而不能一起工作的类可以一起工作。

核心思想转换接口,兼容协作

  • 对象适配器(推荐):使用组合,更灵活,可以适配多个不同的被适配者
  • 类适配器:使用继承,在某些语言中更简洁,但Java中受限于单继承

在Spring框架中,适配器模式被大量用于集成各种不同的组件和技术,提供了极大的灵活性和扩展性。

posted @ 2025-09-01 12:01  庞去广  阅读(16)  评论(0)    收藏  举报