适配器模式是两个不兼容接口间的桥梁,属于结构型模式。适配器模式分为三类,类适配器模式,对象适配器模式,接口适配器模式。我们生活中有很多适配器模式的例子,例如我们给手机充电,家庭电压是220V直流,手机的电压是5V交流,但是我们依然可以直接给手机充电,就是因为充电器充当了适配器的角色。
例子:把220V直流适配成5V交流。
类图:
Voltage220V类
package com.jc.adapter.classadapter; /** * @program: 设计模式 * @description:被适配者 * @author: Mr.Wang * @create: 2021-06-16 20:03 **/ public class Voltage220V { public int output220V() { int src = 220; return src; } }
Voltage5V接口
package com.jc.adapter.classadapter; /** * 目标接口 */ public interface Voltage5V { int output5V(); }
VoltageApdapter类
package com.jc.adapter.classadapter;/** * @program: 设计模式 * * @description: 适配器 * * @author: Mr.Wang * * @create: 2021-06-16 20:05 **/ public class VoltageAdapter extends Voltage220V implements Voltage5V { @Override public int output5V() { int src = output220V(); src = src / 44; System.out.println("220V已经适配成5V啦!可以充电啦!"); return src; } }
Phone类
package com.jc.adapter.classadapter;/** * @program: 设计模式 * * @description: * * @author: Mr.Wang * * @create: 2021-06-16 20:06 **/ public class Phone { //充电 public void charging(Voltage5V voltage5V){ if (voltage5V.output5V() == 5){ System.out.println("电压为5V~可以充电"); }else if(voltage5V.output5V() > 5){ System.out.println("电压大于5V~不可以充电!"); } } }
Client
package com.jc.adapter.classadapter;/** * @program: 设计模式 * * @description: * * @author: Mr.Wang * * @create: 2021-06-16 20:08 **/ public class Client { public static void main(String[] args) { System.out.println("========类适配器模式========="); Phone phone = new Phone(); phone.charging(new VoltageAdapter()); // ========类适配器模式========= // 220V已经适配成5V啦!可以充电啦! // 电压为5V~可以充电 } }
java是单继承模式,这里适配器继承了220V直流,实现了5V交流接口,接口可以是很多个,但是只能继承一个。
我们继承220V直流的目的时什么?
就是想用他里边的output220V这个方法,然后通过一顿操作将他改成5V直流。根据合成符用原则,如果B类仅仅想使用A类中的方法,我们尽量使用组合和聚合的方式,而不是通过继承。继承带来的后果就是:侵入性,不够灵活,高耦合。
所以我们能用组合和聚合就不要使用继承。
所以我们引出对象适配器模式
我们只需要把220V直流那个类聚合到适配器类里边就ok了。
类图
新的适配器类
package com.jc.adapter.objectadapter; /** * @program: 设计模式 * * @description: 适配器 * * @author: Mr.Wang * * @create: 2021-06-16 20:05 **/ public class VoltageAdapter implements Voltage5V { //聚合进来 Voltage220V voltage220V; public VoltageAdapter(Voltage220V voltage220V) { this.voltage220V = voltage220V; } @Override public int output5V() { int src = voltage220V.output220V(); src = src / 44; System.out.println("220V已经适配成5V啦!可以充电啦!"); return src; } }
Client
package com.jc.adapter.objectadapter; import jdk.internal.dynalink.beans.StaticClass; import java.util.*; /** * @program: 设计模式 * * @description: * * @author: Mr.Wang * * @create: 2021-06-16 20:08 **/ public class Client { public static void main(String[] args) { System.out.println("========对象适配器模式========="); Phone phone = new Phone(); phone.charging(new VoltageAdapter(new Voltage220V())); // ========对象适配器模式========= // 220V已经适配成5V啦!可以充电啦! // 电压为5V~可以充电 } }
依然可以实现相同效果,相比于类适配器更加灵活,耦合性低。
1.接口适配器模式又被称为 缺省适配器模式;
2.当不需要全部实现接口提供的方法时,可先设计一个抽象类实现接口,并为该接口中每个方法提供一个默认实现(空方法),那么该抽象类的子类可有选择地覆盖父类的某些方法来实现需求。
类图
Interface4
package com.jc.adapter.interfaceadapter; public interface Interface4 { void m1(); void m2(); void m3(); void m4(); void m5(); }
AbstractAdapter
package com.jc.adapter.interfaceadapter;/** * @program: 设计模式 * * @description: * * @author: Mr.Wang * * @create: 2021-06-17 21:54 **/ public abstract class AbstractAdapter implements Interface4 { @Override public void m1() { } @Override public void m2() { } @Override public void m3() { } @Override public void m4() { } @Override public void m5() { } }
ConcreteAdapter1
package com.jc.adapter.interfaceadapter;/** * @program: 设计模式 * * @description: * * @author: Mr.Wang * * @create: 2021-06-17 21:59 **/ public class ConcreteAdapter1 extends AbstractAdapter { @Override public void m1() { System.out.println("第一个适配器:我要用m1 所以实现了m1"); } public ConcreteAdapter1(){ System.out.println("=====我是第一个适配器====我只实现了m1,m3"); } @Override public void m3() { System.out.println("第一个适配器:我要用m3 所以实现了m3"); } }
ConcreteAdapter2
package com.jc.adapter.interfaceadapter;/** * @program: 设计模式 * * @description: * * @author: Mr.Wang * * @create: 2021-06-17 21:59 **/ public class ConcreteAdapter2 extends AbstractAdapter { public ConcreteAdapter2(){ System.out.println("=====我是第二个适配器====我只实现了m2,m4"); } @Override public void m2() { System.out.println("第二个适配器:我要用m2 所以实现了m2"); } @Override public void m4() { System.out.println("第二个适配器:我要用m4 所以实现了m4"); } }
Client
package com.jc.adapter.interfaceadapter;/** * @program: 设计模式 * * @description: * * @author: Mr.Wang * * @create: 2021-06-17 21:54 **/ public class Client { public static void main(String[] args) { //第一个适配器 AbstractAdapter adapter1 = new ConcreteAdapter1(); adapter1.m1(); adapter1.m3(); //第二个适配器 AbstractAdapter adapter2 = new ConcreteAdapter2(); adapter2.m2(); adapter2.m4(); // =====我是第一个适配器====我只实现了m1,m3 // 第一个适配器:我要用m1 所以实现了m1 // 第一个适配器:我要用m3 所以实现了m3 // =====我是第二个适配器====我只实现了m2,m4 // 第二个适配器:我要用m2 所以实现了m2 // 第二个适配器:我要用m4 所以实现了m4 } }
通过打印结果我们实现了自己想要的适配器,并实现了自己的操作。
1.HttpServlet继承GenericServlet,GenericServlet空实现于javax.servlet.Servlet
2.在springMVC框架中的应用
HandlerAdapter
public interface HandlerAdapter { boolean supports(Object var1); @Nullable ModelAndView handle(HttpServletRequest var1, HttpServletResponse var2, Object var3) throws Exception; long getLastModified(HttpServletRequest var1, Object var2); }
HttpRequestHandlerAdapter (其中一个具体的适配器)
public class HttpRequestHandlerAdapter implements HandlerAdapter { public HttpRequestHandlerAdapter() { } public boolean supports(Object handler) { return handler instanceof HttpRequestHandler; } @Nullable public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { ((HttpRequestHandler)handler).handleRequest(request, response); return null; } public long getLastModified(HttpServletRequest request, Object handler) { return handler instanceof LastModified ? ((LastModified)handler).getLastModified(request) : -1L; } }
如何应用的?
DispatchServlet中的doDispatch方法
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { //根据HandlerMapping获取对应的Handler(Controller) mappedHandler = this.getHandler(processedRequest); //没有根据映射拿到Handler的话报错。 if (mappedHandler == null) { this.noHandlerFound(processedRequest, response); return; } //从handlerAdapters选择一个支持具体的Hander的适配器 HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler()); //根据适配器进行处理,然后返回结果. mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); }
getHandlerAdapter方法
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException { if (this.handlerAdapters != null) { //遍历handlerAdapters选择合适的HandlerAdapter for (HandlerAdapter adapter : this.handlerAdapters) { if (adapter.supports(handler)) { return adapter; } } } throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler"); }
好:
1、将目标类和适配者类解耦,(譬如上边的,将DispatchServlet和具体的适配器解耦)
2、增加了类的透明性和复用性,将具体的实现封装在适配者类中,对于客户端类来说是透明的,而且提高了适配者的复用性
3、灵活性和扩展性都非常好,符合开闭原则
不好:
适配器编写过程需要结合业务场景全面考虑,可能会增加系统的复杂
降低代码可读性,过多使用适配器会使系统代码变得很难懂。