定义:
将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。
优点:
1、可以让任何两个没有关联的类一起运行。
2、提高了类的复用。
3、灵活性好
缺点:
过多地使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是 A 接口,其实内部被适配成了 B 接
口的实现,一个系统如果太多出现这种情况,无异于一场灾难。
以自定义Spring架构来说明
适配器视图渲染
做视图解析的时候,有不同的解析方式,比如有直接输入json数据、重定向、转发、输出文件流等多种方式。通常采用哪种解析方式由执行方法的返回值决定,例如返回一个字符串,我们可以把返回的字符串当做响应的页面,这时候可以采用转发的方式,如果返回的是一个javabean,这时候我们可以采用输出json字符串的方式解析。像这一块的实现,我们可以采用适配器模式实现。
实现步骤:
1、定义一个视图解析接口ViewHandler,提供2种解析方式,分别为json输出和forward
2、为接口实现每种解析方式。分别创建PrintViewHandler和ForwardViewHandler
3、创建一个视图渲染接口View,View中提供渲染方法render
4、创建View的渲染实现ViewAdapter,通过提供的相应结果,来创建对应的试图解析器,并调用解析方式
适配器模式实现视图解析
1)创建视图解析器接口
public interface ViewHandler {
//json输出
default void print(HttpServletResponse response,Object result){};
//转发
default void forward(HttpServletRequest request,HttpServletResponse response,Object result){}
}
2)创建json解析和转发
JSON解析对象: PrintViewHandler
public class PrintViewHandler implements ViewHandler {
//输出json
@Override
public void print(HttpServletResponse response, Object result) {
try {
response.setContentType("application/json;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.write(JSON.toJSONString(result));
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
转发解析对象: ForwardViewHandler
public class ForwardViewHandler implements ViewHandler {
//转发
@Override
public void forward(HttpServletRequest request, HttpServletResponse response, Object result) {
try {
request.getRequestDispatcher(result.toString()).forward(request,response);
} catch (Exception e) {
e.printStackTrace();
}
}
}
3)视图渲染接口和实现
视图渲染接口: View
public interface View {
//渲染方法
void render(HttpServletRequest request, HttpServletResponse response,Object result);
}
视图渲染实现: ViewAdapter
public class ViewAdapter implements View {
private ViewHandler viewHandler;
//渲染实现
@Override
public void render(HttpServletRequest request, HttpServletResponse response, Object result) {
if(result instanceof String){
//转发
viewHandler = new ForwardViewHandler();
viewHandler.forward(request,response,result);
}else{
viewHandler = new PrintViewHandler();
viewHandler.print(response,result);
}
}
}
我们创建一个类 DispacherServlet ,继承BaseInit,同时在 web.xml 中把 BaseInit 换成 DispacherServlet ,并重写 service 方法,实现拦截所有用户请求,在 service 中使用执行反射调用,然后调用刚才写好的适配器查找对应的渲染方式执行渲染,代码如下:
public class DispacherServlet extends BaseInit {
private View view;
/***
* 拦截用户所有请求
*/
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取uri
String uri = req.getRequestURI();
//反射调用
Object result = invoke(uri);
if(result!=null){
//响应结果给用户
view = new ViewAdapter();
view.render(req,resp,result);
}
}
//执行反射调用
public Object invoke(String uri){
try {
//从methods中获取指定的方法
Method method = XmlBeanFactory.methods.get(uri);
if(method!=null){
//执行反射调用
//Class<?> clazz = method.getDeclaringClass(); //获取方法所在类
//return method.invoke(clazz.newInstance());
//通过工厂获取实例
Object instance = beanFactory.getUrlBean(uri);
return method.invoke(instance);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}