第四章 设计模式之适配器模式

适配器模式定义

系统需用用到原有的类的功能,但是原有的类不符合现在的系统接口规范,需要将原有的类改造成符合现在系统的接口规范,使得两个因为接口规范不能在一起工作的类能在一起工作。

适配器模式的关键类

目标接口(Target):当前系统所期待的接口,可以是接口或者抽象类。

适配者(Adaptee):不符合系统要求的类,需要对其进行改造,让它符合系统规范。

适配器(Adapter):它是一个转换类,通过继承或者引用适配者,将适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。

适配器模式的种类

类适配器:主要是适配器继承适配者,然后实现目标接口,重写目标接口的相关方法,在重写的方法中调用适配者的方法。

对象适配器:适配器引用适配者,适配器实现目标接口,重写目标接口的相关方法,在重写的方法中调用适配者的方法。

对象适配器相比类适配器更加灵活,因为对象适配器中可以引用不同的适配者。

适配器模式的好处

在不改变适配者类结构的情况下,就能让适配者的功能得到复用。
让适配者和客户端解耦,客户端拿到了自己想要的功能,而不需要知道这个功能是通过适配器调用适配者得到的。

适配器模式结构示意图

类适配器模式(adapter pattern)结构图:
类适配器模式

对象适配器模式(object adapter pattern)结构图:
对象适配器模式结构图

适配者应用举例

spring MVC中的适配器模式
Spring MVC中的适配器模式主要用于执行目标 Controller 中的请求处理方法。

在Spring MVC中,DispatcherServlet 作为用户,HandlerAdapter 作为期望接口,具体的适配器实现类用于对目标类进行适配,Controller 作为需要适配的类。

为什么要在 Spring MVC 中使用适配器模式?Spring MVC 中的 Controller 种类众多,不同类型的 Controller 通过不同的方法来对请求进行处理。如果不利用适配器模式的话,DispatcherServlet 直接获取对应类型的 Controller,需要的自行来判断,像下面这段代码一样:

if(mappedHandler.getHandler() instanceof MultiActionController){  
   ((MultiActionController)mappedHandler.getHandler()).xxx  
}else if(mappedHandler.getHandler() instanceof XXX){  
    ...  
}else if(...){  
   ...  
}  

这样假设如果我们增加一个 HardController,就要在代码中加入一行 if(mappedHandler.getHandler() instanceof HardController),这种形式就使得程序难以维护,也违反了设计模式中的开闭原则 – 对扩展开放,对修改关闭。

public interface HandlerAdapter {
    boolean supports(Object var1);

    ModelAndView handle(HttpServletRequest var1, HttpServletResponse var2, Object var3) throws Exception;

    long getLastModified(HttpServletRequest var1, Object var2);
}

现该接口的适配器每一个 Controller 都有一个适配器与之对应,这样的话,每自定义一个 Controller 需要定义一个实现 HandlerAdapter 的适配器。

springmvc 中提供的 Controller 实现类有如下

spring mvc Controller 提供的实现类

springmvc 中提供的 HandlerAdapter 实现类如下

spring mvc HandlerAdapter 提供的实现类

来看一下SimpleControllerHandlerAdapter适配器  是如何处理请求的

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 long getLastModified(HttpServletRequest request, Object handler) {
		if (handler instanceof LastModified) {
			return ((LastModified) handler).getLastModified(request);
		}
		return -1L;
	}
 
}

当Spring容器启动后,会将所有定义好的适配器对象存放在一个List集合中,当一个请求来临时,DispatcherServlet 会通过 handler 的类型找到对应适配器,并将该适配器对象返回给用户,然后就可以统一通过适配器的 hanle() 方法来调用 Controller 中的用于处理请求的方法

public class DispatcherServlet extends FrameworkServlet {
    private List<HandlerAdapter> handlerAdapters;
    
    //初始化handlerAdapters
    private void initHandlerAdapters(ApplicationContext context) {
        //..省略...
    }
    
    // 遍历所有的 HandlerAdapters,通过 supports 判断找到匹配的适配器
    protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
		for (HandlerAdapter ha : this.handlerAdapters) {
			if (logger.isTraceEnabled()) {
				logger.trace("Testing handler adapter [" + ha + "]");
			}
			if (ha.supports(handler)) {
				return ha;
			}
		}
	}
	
	// 分发请求,请求需要找到匹配的适配器来处理
	protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
		HttpServletRequest processedRequest = request;
		HandlerExecutionChain mappedHandler = null;

		// Determine handler for the current request.
		mappedHandler = getHandler(processedRequest);
			
		// 确定当前请求的匹配的适配器.
		HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

		ha.getLastModified(request, mappedHandler.getHandler());
					
		mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
    }
	// ...省略...
}	

通过适配器模式我们将所有的 controller 统一交给 HandlerAdapter 处理,免去了写大量的 if-else 语句对 Controller 进行判断,也更利于扩展新的 Controller 类型。

参考文章:https://whirlys.blog.csdn.net/article/details/82780560

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值