一、概念
将一个接口转换成客户希望的另一个接口,使接口不兼容的那些类可以一起工作。
二、Spring MVC 中的适配器模式
1、面临的问题
Spring MVC 中Controller的类型不同,类型不同,调用的方式就不确定。
①实现Controller的接口
public class ControllerDemo1 implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest req, HttpServletResponse resp) throws Exception {
System.out.println("===方式一:实现Controller接口===");
//使用ModelAndView去响应
ModelAndView mav = new ModelAndView();//模型数据和视图对象
mav.addObject("msg","helloworld");//添加模型数据
mav.setViewName("/hello.jsp");//设置视图路径 是一个转发
return mav;
}
}
Spring MVC配置:
<bean id="/demo1" class="com.zhengqing.controller.ControllerDemo1" ></bean>
②实现HttpRequestHandler接口
public class ControllerDemo2 implements HttpRequestHandler {
@Override
public void handleRequest(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("===实现HttpRequestHandler接口===");
}
}
Spring MVC配置:
<bean id="/demo2" class="com.zhengqing.controller.ControllerDemo2" ></bean>
③直接就是一个普通JAVA类 (使用注解的方式,注意:要配置全注解!!)
@Controller //创建对象
//@RequestMapping("/demo")
public class ControllerDemo3 {
@RequestMapping("/demo3") //配置访问路径 注意:如果类上面添加了@RequestMapping("/demo") 则此时访问将变成/demo/demo3
@ResponseBody
public void test(){
System.out.println("方式三:普通类+注解");
}
}
在SpringMVC的配置中添加自动扫描(作用:让spring管理这个bean即可,无需指定路径,在方法上面通过@RequestMapping指定即可!)
<!-- 全注解扫描所有的包 -->
<context:component-scan base-package="com.zhengqing.controller" />
如果直接调用controller方法,则会出现如下情况
if(mappedHandler.getHandler() instanceof MultiActionController){
((MultiActionController)mappedHandler.getHandler()).xxx
}else if(mappedHandler.getHandler() instanceof XXX){
...
}else if(...){
...
}
这样假设如果我们增加一个HardController,就要在代码中加入一行 if(mappedHandler.getHandler() instanceof HardController)
这种形式就使得程序难以维护,也违反了设计模式中的开闭原则 -- 对扩展开放,对修改关闭。
2、解决方式
因此Spring定义了一个,使得每一种Controller有一种对应的适配器实现类, 让适配器代替controller执行相应的方法。这样在扩展Controller 时,只需要增加一个适配器类就完成了SpringMVC的扩展了,真的是很精巧的做法!
三、实例代码解析
以下是三种Controller实现
public interface Controller {
}
public class HttpController implements Controller{
public void doHttpHandler(){
System.out.println("http...");
}
}
public class SimpleController implements Controller{
public void doSimplerHandler(){
System.out.println("simple...");
}
}
public class AnnotationController implements Controller{
public void doAnnotationHandler(){
System.out.println("annotation...");
}
}
定义一个Adapter接口
public interface HandlerAdapter {
public boolean supports(Object handler);
public void handle(Object handler);
}
下面编写适配器类
public class SimpleHandlerAdapter implements HandlerAdapter {
public void handle(Object handler) {
((SimpleController)handler).doSimplerHandler();
}
public boolean supports(Object handler) {
return (handler instanceof SimpleController);
}
}
public class HttpHandlerAdapter implements HandlerAdapter {
public void handle(Object handler) {
((HttpController)handler).doHttpHandler();
}
public boolean supports(Object handler) {
return (handler instanceof HttpController);
}
}
public class AnnotationHandlerAdapter implements HandlerAdapter {
public void handle(Object handler) {
((AnnotationController)handler).doAnnotationHandler();
}
public boolean supports(Object handler) {
return (handler instanceof AnnotationController);
}
}
模拟一个DispatcherServlet
public class DispatchServlet {
public static List<HandlerAdapter> handlerAdapters = new ArrayList<HandlerAdapter>();
public DispatchServlet(){
handlerAdapters.add(new AnnotationHandlerAdapter());
handlerAdapters.add(new HttpHandlerAdapter());
handlerAdapters.add(new SimpleHandlerAdapter());
}
public void doDispatch(){
//此处模拟SpringMVC从request取handler的对象,仅仅new出,可以出,
//不论实现何种Controller,适配器总能经过适配以后得到想要的结果
// HttpController controller = new HttpController();
// AnnotationController controller = new AnnotationController();
SimpleController controller = new SimpleController();
//得到对应适配器
HandlerAdapter adapter = getHandler(controller);
//通过适配器执行对应的controller对应方法
adapter.handle(controller);
}
public HandlerAdapter getHandler(Controller controller){
for(HandlerAdapter adapter: this.handlerAdapters){
if(adapter.supports(controller)){
return adapter;
}
}
return null;
}
public static void main(String[] args){
new DispatchServlet().doDispatch();
}
}