定义
适配器模式,将一个类的接口转换成客户希望的另外一个接口。Adapter 模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
再理解
适配器就是一个转接头。
用苹果手机的人(虽然我没用过),应该对耳机转接头很熟悉。
苹果的接口是扁平的,耳机的接口是圆的。显然不匹配。但是,只要买个转接头就可以连在一起了。
电流就可以通过转接头从手机流到耳机,让耳机工作起来了。
在编程中,有的接口是“扁平”的,但是我们只接受“圆”接口的数据,那肿么办?手撸一个“转接头”,把他们连接起来就可以了。数据就可以向电流一样,从“扁平”接口,流向“转接头”,再流向“圆”接口,让我们的调用端“工作”起来。
分类
适配器有三种实现方式,分别是:
- 类适配器
- 对象适配器
- 接口适配器
下边就一一举例解决。
案例
假设我们要用浏览器访问一个网页。
数据库查询的数据封装在JavaBean中
前端需要的是Json类型的数据
我们做个“转接头”一段接收JavaBean的数据,转化成Json数据,再返回给浏览器。
下边就按照前两种实现方式开始撸代码。
类适配器
UML类图
代码
JavaBean
package 适配器模式.类适配器;
public class JavaBean {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
IJson
package 适配器模式.类适配器;
public interface IJson {
public String outJson();
}
DataAdapter
package 适配器模式.类适配器;
public class DataAdapter extends JavaBean implements IJson {
@Override
public String outJson() {
return "{'name':'"+getName()+"','age':'"+getAge()+"'}";
}
}
Browser
package 适配器模式.类适配器;
public class Browser {
public void sayJson(IJson iJson) {
System.out.println(iJson.outJson());
}
}
Client
package 适配器模式.类适配器;
public class Browser {
public void sayJson(IJson iJson) {
System.out.println(iJson.outJson());
}
}
运行结果
{'name':'null','age':'0'}
优点
- 让不兼容的两个接口之间可以进行数据交换。
- 由于继承了被适配者,所以它可以根据需求重写被适配者的方法,使得Adapter的灵活请增强了。
缺点
- Java是单继承机制,所以适配器需要继承被适配者,因此要求目标必须是接口,有一定的限制性。
- 被适配者的方法在Adapter中会暴露出来,增加了使用成本
对象适配器
UML类图
代码
JavaBean
package 适配器模式.类适配器;
public class JavaBean {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
IJson
package 适配器模式.类适配器;
public interface IJson {
public String outJson();
}
DataAdapter
package 适配器模式.对象适配器;
public class DataAdapter implements IJson{
private JavaBean javaBean;
public DataAdapter(JavaBean javaBean) {
this.javaBean = javaBean;
}
@Override
public String outJson() {
return "{'name':'"+javaBean.getName()+"','age':'"+javaBean.getAge()+"'}";
}
}
Browser
package 适配器模式.类适配器;
public class Browser {
public void sayJson(IJson iJson) {
System.out.println(iJson.outJson());
}
}
Client
package 适配器模式.对象适配器;
public class Client {
public static void main(String[] args) {
Browser browser = new Browser();
browser.sayJson(new DataAdapter(new JavaBean()));
}
}
运行结果
{'name':'null','age':'0'}
优点
- 让不兼容的两个接口之间可以进行数据交换。
- 没有使用继承,而是用组合,直接把被适配者当作自己的一个参数,成本低。
缺点
- 由于
未继承
被适配者,所以它不可以
根据需求重写被适配者的方法,灵活性不如类适配器。
接口适配器
这个适配器和上边两个适配器适配的内容不一样,主要是为了解决,无意义复写。
当我们实现一个接口时,接口中所有的方法,不管我们用不用得到,都得去实现一遍,而是用接口适配器后,就不需要去实现那些用不到的方法了。
UML类图
代码
Interface
package 适配器模式.接口适配器;
public interface Interface {
void m1();
void m2();
void m3();
void m4();
void m5();
void m6();
void m7();
void m8();
}
AbsAdapter
package 适配器模式.接口适配器;
public abstract class AbsAdapter implements Interface{
@Override
public void m1() {
// TODO 自动生成的方法存根
}
@Override
public void m2() {
// TODO 自动生成的方法存根
}
@Override
public void m3() {
// TODO 自动生成的方法存根
}
@Override
public void m4() {
// TODO 自动生成的方法存根
}
@Override
public void m5() {
// TODO 自动生成的方法存根
}
@Override
public void m6() {
// TODO 自动生成的方法存根
}
@Override
public void m7() {
// TODO 自动生成的方法存根
}
@Override
public void m8() {
// TODO 自动生成的方法存根
}
}
Client
package 适配器模式.接口适配器;
public class Client{
public static void main(String[] args) {
AbsAdapter absAdapter = new AbsAdapter() {
@Override
public void m3() {
System.out.println("需要用到那个方法,就复写那个方法");
}
};
absAdapter.m3();
}
}
运行结果
需要用到那个方法,就复写那个方法
优点
可以不需要多次实现用不到的接口方法。
个人学习总结,如果有什么不对的,希望路过的大佬指正