Java设计模式之适配器模式

适配器模式

1. 基本介绍

  1. 适配器模式,将某个类的接口转换成客户端期望的另一个接口表示。主要目的是让原本接口不兼容的两个类可以协同工作。适配器的别名为包装器
  2. 属于结构型模式
  3. 主要分为三类:类适配器模式、对象适配器模式、接口适配器模式。

2. 工作原理

  1. 将一种接口转换成另一种接口,让原本接口不兼容的类可以兼容。
  2. 从用户角度是无法看到被适配者的,因此是解耦的。
  3. 用户直接调用适配器转化出来的接口,适配器再调用被适配者的接口。

3. 类适配器模式

3.1 基本介绍

适配器类Adapter通过继承被适配类Source,并实现目标接口Target,从而完成从SourceTarget的转变。

3.2 手机充电例子

充电器相当于适配器Adapter,被适配者相当于220V电压 Source,目标接口相当于5V电压 Target

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xuTipCdz-1621763591065)(resource/1621748802643.png)]

3.3 代码实现

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AWvGb2pp-1621763591073)(resource/1621749891219.png)]

/**
 * @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 注意事项

  1. Java是单继承机制,所有类适配器继承Source类是一个缺点,因为这就要求Target必须是接口,有一定局限性。【没有遵循合成复用原则】
  2. 由于继承了Source类,所有可以根据需要重写父类方法,使得Adapter灵活性增强。【但是有可能会违背里式替换原则

4. 对象适配器模式

4.1 基本介绍

  1. 在类适配器模式基础上,把Adapter对Source的继承关系,改为持有Source的实例。即:持有Source实例、实现Target接口,完成从Source到Target的适配。
  2. 也就是根据合成复用原则,把继承关系,改为关联关系。
  3. 对象适配器模式是适配器模式常用的一种。

4.2 代码实现

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KUrBMrvy-1621763591081)(resource/1621756668831.png)]

// 在类适配器的基础上修改

/**
 * @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 小结

  1. 遵循合成复用原则,不再要求必须继承Source类,也不再要求Target必须是接口。
  2. 灵活性增强。

5. 接口适配器模式

5.1 基本介绍

  1. 当不需要全部实现接口中的方法时,可以先设计一个抽象类去实现该接口,并为每一个方法提供一个空实现,则抽象类的子类就能有选择地覆盖部分方法。
  2. 适用于不需要实现所有接口的情况。

5.2 代码描述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Oo7oqAun-1621763591092)(resource/1621757704439.png)]

/**
 * @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源码,编写其简化版的适配器模式。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cqiIrvj1-1621763591105)(resource/1621763529409.png)]

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
  • 以上内容均记载在我的开源项目中
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值