适配器模式 (Adapter Pattern)
将不兼容的接口转换为兼容的接口,实现系统间的协同工作
目录
概述
适配器模式是一种结构型设计模式,它允许将一个类的接口转换成客户端希望的另一个接口。适配器让原本接口不兼容的类可以合作无间。
适用场景
- 使用现有类,但其接口不符合需求
- 需要统一多个类的接口
- 系统需要与第三方库集成
- 旧系统升级兼容
实现方式
1. 类适配器(继承)
// 目标接口
public interface MediaPlayer {
void play(String audioType, String fileName);
}
// 被适配者
public class AdvancedMediaPlayer {
public void playMp4(String fileName) {
System.out.println("播放 MP4: " + fileName);
}
public void playVlc(String fileName) {
System.out.println("播放 VLC: " + fileName);
}
}
// 类适配器(继承)
public class MediaAdapter extends AdvancedMediaPlayer implements MediaPlayer {
@Override
public void play(String audioType, String fileName) {
if ("mp4".equalsIgnoreCase(audioType)) {
playMp4(fileName);
} else if ("vlc".equalsIgnoreCase(audioType)) {
playVlc(fileName);
}
}
}
// 使用
MediaPlayer player = new MediaAdapter();
player.play("mp4", "movie.mp4");2. 对象适配器(组合)
// 对象适配器(推荐)
public class MediaAdapter implements MediaPlayer {
private AdvancedMediaPlayer advancedPlayer;
public MediaAdapter(AdvancedMediaPlayer player) {
this.advancedPlayer = player;
}
@Override
public void play(String audioType, String fileName) {
if ("mp4".equalsIgnoreCase(audioType)) {
advancedPlayer.playMp4(fileName);
} else if ("vlc".equalsIgnoreCase(audioType)) {
advancedPlayer.playVlc(fileName);
}
}
}实际应用:支付适配器
// 统一的支付接口
public interface PaymentProcessor {
void processPayment(BigDecimal amount);
void refund(String transactionId);
}
// 支付宝 SDK
public class AlipaySDK {
public void pay(double amount) {
System.out.println("支付宝支付: " + amount);
}
public void doRefund(String id) {
System.out.println("支付宝退款: " + id);
}
}
// 微信支付 SDK
public class WechatPaySDK {
public void makePayment(BigDecimal amount) {
System.out.println("微信支付: " + amount);
}
public void returnMoney(String orderId) {
System.out.println("微信退款: " + orderId);
}
}
// 支付宝适配器
public class AlipayAdapter implements PaymentProcessor {
private AlipaySDK alipay = new AlipaySDK();
@Override
public void processPayment(BigDecimal amount) {
alipay.pay(amount.doubleValue());
}
@Override
public void refund(String transactionId) {
alipay.doRefund(transactionId);
}
}
// 微信适配器
public class WechatPayAdapter implements PaymentProcessor {
private WechatPaySDK wechatPay = new WechatPaySDK();
@Override
public void processPayment(BigDecimal amount) {
wechatPay.makePayment(amount);
}
@Override
public void refund(String transactionId) {
wechatPay.returnMoney(transactionId);
}
}
// 支付服务
@Service
public class PaymentService {
private final Map<String, PaymentProcessor> processors = new HashMap<>();
public PaymentService() {
processors.put("alipay", new AlipayAdapter());
processors.put("wechat", new WechatPayAdapter());
}
public void pay(String type, BigDecimal amount) {
PaymentProcessor processor = processors.get(type);
if (processor == null) {
throw new IllegalArgumentException("不支持的支付方式");
}
processor.processPayment(amount);
}
}框架中的应用
Spring MVC HandlerAdapter
// Spring 使用适配器模式适配不同类型的 Controller
public interface HandlerAdapter {
boolean supports(Object handler);
ModelAndView handle(HttpServletRequest request,
HttpServletResponse response,
Object handler);
}
// 适配不同的 Controller 类型
public class SimpleControllerHandlerAdapter implements HandlerAdapter {
@Override
public boolean supports(Object handler) {
return handler instanceof Controller;
}
@Override
public ModelAndView handle(HttpServletRequest request,
HttpServletResponse response,
Object handler) {
return ((Controller) handler).handleRequest(request, response);
}
}
// 适配注解 Controller
public class RequestMappingHandlerAdapter implements HandlerAdapter {
// 处理 @Controller + @RequestMapping
}Java IO 适配器
// InputStreamReader 是字节流到字符流的适配器
InputStream inputStream = new FileInputStream("file.txt");
Reader reader = new InputStreamReader(inputStream, "UTF-8");
// OutputStreamWriter 是字符流到字节流的适配器
Writer writer = new OutputStreamWriter(System.out);Arrays.asList()
// 数组转列表的适配器
String[] array = {"a", "b", "c"};
List<String> list = Arrays.asList(array); // 适配器视图新旧系统兼容
// 旧的用户系统接口
public interface OldUserService {
String findUserName(int userId);
}
// 新的用户系统接口
public interface NewUserService {
User findById(Long userId);
}
// 新的实现
public class NewUserServiceImpl implements NewUserService {
@Override
public User findById(Long userId) {
return new User(userId, "username");
}
}
// 适配器:让新系统兼容旧接口
@Component
public class UserServiceAdapter implements OldUserService {
@Autowired
private NewUserService newUserService;
@Override
public String findUserName(int userId) {
User user = newUserService.findById((long) userId);
return user != null ? user.getName() : null;
}
}优缺点
| 优点 | 缺点 |
|---|---|
| 解耦目标类和被适配者 | 增加系统复杂度 |
| 复用现有类 | 过多适配器使代码难以理解 |
| 扩展性好 |
总结
适配器模式是解决接口不兼容问题的有效手段。对象适配器比类适配器更灵活(通过组合而非继承),是更推荐的方式。在集成第三方库、系统升级等场景中非常实用。