适配器模式(Adapter)就是由源到目标的一个适配,通常我们定义的接口或者类里面提供了好多方法,但是有时候用起来不是很符合,但是我们不能修改源码,那确实也不是一个好的方法,这样就提供了适配器这个类,用一个类来时源能匹配目标就可以了。
在Spring,IO里面都有这方面的设计,最简单的BeanUtils里面的转换器,就是当你没有定义相应的vo类似那个的时候,可以自动一个转化器然后应用就可以了。
适配器模式(Adapter)的简单的原理图:
这次我把UML类图也添加了备注,把图片放大了,这样方便查看和复习,同时清楚了实线空心箭头是“继承的”的意思,虚线空心箭头是“实现了”的意思,上面用的是去实现了,其实有的版本上面确切是是用实线箭头,就是关联的意思,其实表达出大致的意思就行了。
适配器模式有两种,一种是类适配器,一种是对象适配器,其宗旨都是解决源对于目标的不匹配,下面分别从简单的例子看两种适配器然后整体分析:
第一种适配器
我的电脑耳机坏了,但是我耳机是USB2.0的插口,不幸运的是我只有一个3.0的耳机了,于是我去买了一个适配器把3.0的和2.0的接到了一起,就能用了,事例代码如下:
- package com.designpattern.adapter;
- public interface USB2 {
- public void need();
- }
- package com.designpattern.adapter;
- public class USB3 {
- public void add() {
- System.out.println("I'm a USB3.0 headset");
- }
- }
- package com.designpattern.adapter;
- public class Adapter extends USB3 implements USB2 {
- @Override
- public void need() {
- this.add();
- }
- }
- package com.designpattern.adapter;
- public class Client {
- public static void main(String[] args) {
- Adapter adapter = new Adapter();
- adapter.add();
- }
- }
这样就直接打印了:
- I'm a USB3.0 headset
这样Adapter继承了USB3这个类,java中的单继承不允许它在继承别的类了,所以就不能再实现别的目标类的需求了,所以这样就叫做类适配器,量身为一个类做的一个适配器。其实这种类的适配模式用于单一源的适配,由于它的源的单一话,代码实现不用写选择逻辑,很清晰;而对象的适配模式则可用于多源的适配,弥补了类适配模式的不足,使得原本用类适配模式需要写很多适配器的情况不复存在,弱点是,由于源的数目可以较多,所以具体的实现条件选择分支比较多,不太清晰。同时在对象的适配器里面,通常是把源或者是目标聚合到适配器里面,就是和适配器拥有共同的生命周期,放在适配器的构造器里面,个人觉得在源放在放在适配器里面比较好,可能多数的时候是在适配器面接收目标的要求,然后通过对要求的分析,解析在用源的实例去调用源的方法的。
下面就简单的写了一个对象的适配器的例子:
我定义了一个类Utils简单的用List存放了三个字符串,作为我的源,但是我的Application用的时候是必须是HashMap,这样我就不能用了,于是定义的一个ListAdapter类,来解决这两个问题,具体代码如下:
- package com.designpattern.adapter;
- import java.util.ArrayList;
- import java.util.List;
- public class Utils {
- @SuppressWarnings("unchecked")
- public static List getElements() {
- List list = new ArrayList();
- list.add("first");
- list.add("second");
- list.add("third");
- return list;
- }
- }
- package com.designpattern.adapter;
- import java.util.HashMap;
- public class Application {
- @SuppressWarnings("unchecked")
- public static void print(HashMap map) {
- for (int i = 0; i < map.size(); i++) {
- System.out.print(map.get(i) + " ");
- }
- }
- }
- package com.designpattern.adapter;
- import java.util.HashMap;
- import java.util.List;
- @SuppressWarnings( { "unchecked", "serial" })
- public class ListAdapter extends HashMap {
- @SuppressWarnings("unchecked")
- private List list;
- @SuppressWarnings("unchecked")
- public ListAdapter(List list) {
- this.list = list;
- }
- public int size() {
- return list.size();
- }
- public Object get(Object i) {
- return list.get((Integer.valueOf(i.toString())).intValue());
- }
- }
- package com.designpattern.adapter;
- public class Client {
- public static void main(String[] args) {
- System.out.println(Utils.getElements());
- ListAdapter listadapter = new ListAdapter(Utils.getElements());
- Application.print(listadapter);
- }
- }
这样就自然的打印处理如下内容:
- [first, second, third]
- first second third
使用适配器模式,可以讲一个系统的接口和本来不相容的另一个系统的类联系起来,从而使得这两个类能够一起工作,强调了对接口的转换。
这里也简单的说一下默认适配器模式:
这个么模式是大多数API接口使用的方式,以方便用户的使用,简单的定义一个接口里面有好多方法,为了不不得不的实现那么多方法,紧接着定义一个抽象类来实现这个接口,这样就可以继承抽象类来重写自己想要的方法而不写过多的没有意义的方法了。简单的例子如下:
- package com.designpattern.adapter;
- public interface Phone {
- public void sendMessage();
- public void surfInternet();
- public void receiveCall();
- public void AsAlarm();
- }
- package com.designpattern.adapter;
- public abstract class ChinaMobile implements Phone {
- @Override
- public void AsAlarm() {
- // TODO Auto-generated method stub
- }
- @Override
- public void receiveCall() {
- // TODO Auto-generated method stub
- }
- @Override
- public void sendMessage() {
- // TODO Auto-generated method stub
- }
- @Override
- public void surfInternet() {
- // TODO Auto-generated method stub
- }
- }
- package com.designpattern.adapter;
- public class MyPhone extends ChinaMobile {
- @Override
- public void AsAlarm() {
- System.out.println("I just use it as a alarm!");
- }
- }