适配器模式
1. 基本介绍
- 适配器模式,将某个类的接口转换成客户端期望的另一个接口表示。主要目的是让原本接口不兼容的两个类可以协同工作。适配器的别名为
包装器
。- 属于
结构型模式
。- 主要分为三类:类适配器模式、对象适配器模式、接口适配器模式。
2. 工作原理
- 将一种接口转换成另一种接口,让原本接口不兼容的类可以兼容。
- 从用户角度是无法看到
被适配者
的,因此是解耦的。- 用户直接调用适配器转化出来的接口,适配器再调用被适配者的接口。
3. 类适配器模式
3.1 基本介绍
适配器类
Adapter
通过继承被适配类Source
,并实现目标接口Target
,从而完成从Source
到Target
的转变。
3.2 手机充电例子
充电器相当于
适配器Adapter
,被适配者相当于220V电压 Source
,目标接口相当于5V电压 Target
。
3.3 代码实现
/**
* @author: zipeng Li
* 2021/5/23 13:51
*/
public class Voltage220V {
public void output220V(){
System.out.println("被适配者:输出220V。。。");
}
}
/**
* @author: zipeng Li
* 2021/5/23 13:50
*/
public interface Voltage5V {
void output5V();
}
/**
* @author: zipeng Li
* 2021/5/23 13:49
*/
public class VoltageAdapter extends Voltage220V implements Voltage5V{
@Override
public void output5V() {
output220V();
System.out.println("经过一系列适配操作。。。");
System.out.println("我是适配器,输出5V电压。。。");
}
}
/**
* @author: zipeng Li
* 2021/5/23 13:55
*/
public class Phone {
void charging(Voltage5V voltage5V){
voltage5V.output5V();
System.out.println("开始充电啦。。。");
}
}
/**
* @author: zipeng Li
* 2021/5/23 13:53
*/
public class Client {
public static void main(String[] args) {
Phone phone = new Phone();
phone.charging(new VoltageAdapter());
}
}
被适配者:输出220V。。。
经过一系列适配操作。。。
我是适配器,输出5V电压。。。
开始充电啦。。。
3.4 注意事项
- Java是单继承机制,所有类适配器继承Source类是一个缺点,因为这就要求Target必须是接口,有一定局限性。【没有遵循合成复用原则】
- 由于继承了Source类,所有可以根据需要重写父类方法,使得Adapter灵活性增强。【但是有可能会违背
里式替换原则
】
4. 对象适配器模式
4.1 基本介绍
- 在类适配器模式基础上,把Adapter对Source的继承关系,改为持有Source的实例。即:持有Source实例、实现Target接口,完成从Source到Target的适配。
- 也就是根据
合成复用原则
,把继承关系,改为关联关系。- 对象适配器模式是适配器模式常用的一种。
4.2 代码实现
// 在类适配器的基础上修改
/**
* @author: zipeng Li
* 2021/5/23 13:49
*/
public class VoltageAdapter implements Voltage5V {
Voltage220V voltage220V;
public VoltageAdapter(Voltage220V voltage220V) {
this.voltage220V = voltage220V;
}
@Override
public void output5V() {
voltage220V.output220V();
System.out.println("经过一系列适配操作。。。");
System.out.println("我是适配器,输出5V电压。。。");
}
}
/**
* @author: zipeng Li
* 2021/5/23 13:53
*/
public class Client {
public static void main(String[] args) {
Phone phone = new Phone();
phone.charging(new VoltageAdapter(new Voltage220V()));
}
}
被适配者:输出220V。。。
经过一系列适配操作。。。
我是适配器,输出5V电压。。。
开始充电啦。。。
4.3 小结
- 遵循
合成复用原则
,不再要求必须继承Source类,也不再要求Target必须是接口。- 灵活性增强。
5. 接口适配器模式
5.1 基本介绍
- 当不需要全部实现接口中的方法时,可以先设计一个抽象类去实现该接口,并为每一个方法提供一个空实现,则抽象类的子类就能有选择地覆盖部分方法。
- 适用于不需要实现所有接口的情况。
5.2 代码描述
/**
* @author: zipeng Li
* 2021/5/23 16:08
*/
public interface Source {
void func01();
void func02();
void func03();
void func04();
}
/**
* @author: zipeng Li
* 2021/5/23 16:11
*/
public abstract class InterfaceAdapter implements Source{
@Override
public void func01() {
}
@Override
public void func02() {
}
@Override
public void func03() {
}
@Override
public void func04() {
}
}
/**
* @author: zipeng Li
* 2021/5/23 16:12
*/
public class Client {
public static void main(String[] args) {
InterfaceAdapter adapter = new InterfaceAdapter() {
@Override
public void func01() {
System.out.println("适配接口1");
}
};
adapter.func01();
}
}
适配接口1
6. SpringMVC的HandlerAdapter
根据SpringMVC源码,编写其简化版的适配器模式。
6.1 Controller接口及其实现
//多种Controller实现
public interface Controller {
}
class HttpController implements Controller {
public void doHttpHandler() {
System.out.println("http...");
}
}
class SimpleController implements Controller {
public void doSimplerHandler() {
System.out.println("simple...");
}
}
class AnnotationController implements Controller {
public void doAnnotationHandler() {
System.out.println("annotation...");
}
}
6.2 HandlerAdapter接口及其实现
///定义一个Adapter接口
public interface HandlerAdapter {
public boolean supports(Object handler);
public void handle(Object handler);
}
// 多种适配器类
class SimpleHandlerAdapter implements HandlerAdapter {
@Override
public void handle(Object handler) {
((SimpleController) handler).doSimplerHandler();
}
@Override
public boolean supports(Object handler) {
return (handler instanceof SimpleController);
}
}
class HttpHandlerAdapter implements HandlerAdapter {
@Override
public void handle(Object handler) {
((HttpController) handler).doHttpHandler();
}
@Override
public boolean supports(Object handler) {
return (handler instanceof HttpController);
}
}
class AnnotationHandlerAdapter implements HandlerAdapter {
@Override
public void handle(Object handler) {
((AnnotationController) handler).doAnnotationHandler();
}
@Override
public boolean supports(Object handler) {
return (handler instanceof AnnotationController);
}
}
6.3 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的对象,
// 适配器可以获取到希望的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) {
//遍历:根据得到的controller(handler), 返回对应适配器
for (HandlerAdapter adapter : handlerAdapters) {
if (adapter.supports(controller)) {
return adapter;
}
}
return null;
}
public static void main(String[] args) {
new DispatchServlet().doDispatch(); // http...
}
}
6.4 运行结果
http...
后序
- 我是一名大三本科生,专业是软件工程【一本】。目前,正在准备找实习以及秋招,意向岗位是Java后端开发工程师。为此,在码云托管了一个项目,以整理我所有所学知识。涉及内容:计算机网络、操作系统、Java基础、主流Java后端框架、设计模式、Web前端框架等内容。欢迎大家访问我的开源项目编程之路
- 码云地址:https://gitee.com/alizipeng/the-way-of-programming
- 以上内容均记载在我的开源项目中