适配器模式
基础概念
什么是适配器模式?
答案: 适配器模式(Adapter Pattern)将一个类的接口转换成客户希望的另一个接口,使得原本由于接口不兼容而不能一起工作的类可以一起工作。
使用场景:
- 系统需要使用现有的类,但其接口不符合需求
- 想要建立一个可以重复使用的类
- 需要统一多个类的接口
优点:
- 提高类的复用性
- 增加类的透明性
- 灵活性好
缺点:
- 过多使用会使系统凌乱
类适配器
类适配器的实现?
答案:
java
// 目标接口
public interface Target {
void request();
}
// 被适配者
public class Adaptee {
public void specificRequest() {
System.out.println("特殊请求");
}
}
// 类适配器(通过继承)
public class ClassAdapter extends Adaptee implements Target {
@Override
public void request() {
specificRequest();
}
}
// 使用
Target target = new ClassAdapter();
target.request();对象适配器
对象适配器的实现?
答案:
java
// 目标接口
public interface Target {
void request();
}
// 被适配者
public class Adaptee {
public void specificRequest() {
System.out.println("特殊请求");
}
}
// 对象适配器(通过组合)
public class ObjectAdapter implements Target {
private Adaptee adaptee;
public ObjectAdapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public void request() {
adaptee.specificRequest();
}
}
// 使用
Adaptee adaptee = new Adaptee();
Target target = new ObjectAdapter(adaptee);
target.request();推荐使用对象适配器,因为组合优于继承。
实际应用
日志适配器
答案:
java
// 目标接口:统一的日志接口
public interface Logger {
void log(String message);
}
// 被适配者:Log4j
public class Log4jLogger {
public void logMessage(String msg) {
System.out.println("Log4j: " + msg);
}
}
// 被适配者:Logback
public class LogbackLogger {
public void writeLog(String msg) {
ystem.out.println("Logback: " + msg);
}
}
// Log4j适配器
public class Log4jAdapter implements Logger {
private Log4jLogger log4j;
public Log4jAdapter(Log4jLogger log4j) {
this.log4j = log4j;
}
@Override
public void log(String message) {
log4j.logMessage(message);
}
}
// Logback适配器
public class LogbackAdapter implements Logger {
private LogbackLogger logback;
public LogbackAdapter(LogbackLogger logback) {
this.logback = logback;
}
@Override
public void log(String message) {
logback.writeLog(message);
}
}
// 使用
Logger logger1 = new Log4jAdapter(new Log4jLogger());
logger1.log("使用Log4j记录日志");
Logger logger2 = new LogbackAdapter(new LogbackLogger());
logger2.log("使用Logback记录日志");支付适配器
答案:
java
// 目标接口:统一的支付接口
public interface Payment {
boolean pay(BigDecimal amount);
}
// 被适配者:支付宝SDK
public class AlipaySDK {
public String sendPayment(double money) {
System.out.println("支付宝支付: " + money);
return "success";
}
}
// 被适配者:微信SDK
public class WechatSDK {
public int processPay(String amount) {
System.out.println("微信支付: " + amount);
return 0; // 0表示成功
}
}
// 支付宝适配器
public class AlipayAdapter implements Payment {
private AlipaySDK alipay;
public AlipayAdapter(AlipaySDK alipay) {
this.alipay = alipay;
}
@Override
public boolean pay(BigDecimal amount) {
String result = alipay.sendPayment(amount.doubleValue());
return "success".equals(result);
}
}
// 微信适配器
public class WechatAdapter implements Payment {
private WechatSDK wechat;
public WechatAdapter(WechatSDK wechat) {
this.wechat = wechat;
}
@Override
public boolean pay(BigDecimal amount) {
int result = wechat.processPay(amount.toString());
return result == 0;
}
}
// 使用
Payment payment1 = new AlipayAdapter(new AlipaySDK());
payment1.pay(new BigDecimal("100.00"));
Payment payment2 = new WechatAdapter(new WechatSDK());
payment2.pay(new BigDecimal("200.00"));Spring中的适配器模式
HandlerAdapter?
答案:
Spring MVC中的HandlerAdapter就是适配器模式的应用。
java
// 处理器适配器接口
public interface HandlerAdapter {
boolean supports(Object handler);
ModelAndView handle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception;
}
// Controller适配器
public class SimpleControllerHandlerAdapter implements HandlerAdapter {
@Override
public boolean supports(Object handler) {
return (handler instanceof Controller);
}
@Override
public ModelAndView handle(HttpServletRequest request,
HttpServletResponse response,
t handler) throws Exception {
return ((Controller) handler).handleRequest(request, response);
}
}
// RequestMapping适配器
public class RequestMappingHandlerAdapter implements HandlerAdapter {
@Override
public boolean supports(Object handler) {
return (handler instanceof HandlerMethod);
}
@Override
public ModelAndView handle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
return ((HandlerMethod) handler).invokeForRequest(request, response);
}
}练习题
- 类适配器和对象适配器的区别?
- 适配器模式和装饰器模式的区别?
- 什么时候使用适配器模式?
- 如何适配多个不兼容的接口?
- Spring MVC的HandlerAdapter如何工作?