适配器模式——得心应手的“粘合剂”
2016-07-19 11:07
197 查看
适配器模式在日常开发中使用率极高,从代码中随处可见的Adapter就可以看出来。在Android中,ListView,GridView到现在最新的RecyclerView都需要使用Adapter,并且在开发中我们遇到的优化问题,出错概率较大的地方也基本来自Adapter,这是一个让人又爱又恨的角色。
言归正传,适配器是将两个不兼容的类融合在一起,它有点像粘合剂,将不同的东西通过一种转换使得它们能够协作起来。例如,经常碰到要在两个没有关系的类型之间进行交互。第一个解决方法时修改各自的接口,但是如果没有源代码要在或者我们不愿意为了一个应用而修改各自的接口,此时我们往往需要使用一个Adapter,在这两种接口之间创建一个接口,这个Adapter会将这两个接口进行兼容,在不修改原有代码的情况下满足需求。
适配器模式把一个类的接口变换陈客户端所期待的另一种接口,从而使原本因接口不匹配而无法再一起工作的两个类能够子啊一起工作。
模式中的角色
目标接口(Target):客户所期待的接口。目标可以是具体的或抽象的类,也可以是接口。
需要适配的类(Adaptee):需要适配的类或适配者类。
适配器(Adapter):通过包装一个需要适配的对象,把原接口转换成目标接口。
实现方式主要有两种:
类的是适配器模式
对象适配器模式
1)类的是适配器模式
UML类图如图所示
类的适配器模式采用继承方式实现
Adaptee.java
package com.test.adapter;
public class Adaptee {
public void specificRequest() {
System.out.println("被适配类...的特异功能");
}
}
Target.java
package com.test.adapter;
public interface Target {
public void request();
}ConcreteTarget.java
package com.test.adapter;
public class ConcreteTarget implements Target{
@Override
public void request() {
// TODO Auto-generated method stub
System.out.println("普通类、、、没有特异功能");
}
}
Adapter.java
package com.test.adapter;
public class Adapter extends Adaptee implements Target{
@Override
public void request() {
// TODO Auto-generated method stub
super.specificRequest();
}
}
最后是客户端
Client.java
package com.test.adapter;
public class Client {
public static void main(String[] args) {
// 使用普通功能类
Target concreteTarget = new ConcreteTarget();
concreteTarget.request();
// 使用特殊功能类,即适配类
Target adapter = new Adapter();
adapter.request();
}
}
运行结果如下
普通类、、、没有特异功能
被适配类...的特异功能
2)对象适配器模式
UML类图如图所示
与类的适配器模式不同的是,对象的适配器模式不是使用继承关系连接到Adaptee类,而是使用代理关系连接到Adaotee类。
此时只需要修改Adapter.java
public class Adapter implements Target{
// 直接关联被适配类
private Adaptee adaptee;
// 可以通过构造函数传入具体需要适配的被适配类对象
public Adapter (Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public void request() {
// TODO Auto-generated method stub
adaptee.specificRequest();
}
}
客户端也要稍微修改一下
public class Client {
public static void main(String[] args) {
// 使用普通功能类
Target concreteTarget = new ConcreteTarget();
concreteTarget.request();
// 使用特殊功能类,即适配类
Target adapter = new Adapter(new Adaptee());
adapter.request();
}
}
只是new Adapter(new Adaptee());构造方法传入了新的参数,其它一样的,运行结果也是一样的。
从类图中我们也知道需要修改的只不过就是 Adapter 类的内部结构,即 Adapter 自身必须先拥有一个被适配类的对象,再把具体的特殊功能委托给这个对象来实现。使用对象适配器模式,可以使得 Adapter 类(适配类)根据传入的 Adaptee 对象达到适配多个不同被适配类的功能,当然,此时我们可以为多个被适配类提取出一个接口或抽象类。这样看起来的话,似乎对象适配器模式更加灵活一点。
总结
Adapter模式的经典实现在于将原本不兼容的接口融合在一起,使之能够很好的进行合作,但是在实际开发中,Adapter模式也有灵活的实现,可以稍微修改一下。例如ListView中的BaseAdapter,SimpleAdapter就稍微做了一下修改。
优点:
1)更好的复用性
2)更好的扩展性
缺点:
过多的使用适配器,会让系统凌乱,不易整体把握。
言归正传,适配器是将两个不兼容的类融合在一起,它有点像粘合剂,将不同的东西通过一种转换使得它们能够协作起来。例如,经常碰到要在两个没有关系的类型之间进行交互。第一个解决方法时修改各自的接口,但是如果没有源代码要在或者我们不愿意为了一个应用而修改各自的接口,此时我们往往需要使用一个Adapter,在这两种接口之间创建一个接口,这个Adapter会将这两个接口进行兼容,在不修改原有代码的情况下满足需求。
适配器模式把一个类的接口变换陈客户端所期待的另一种接口,从而使原本因接口不匹配而无法再一起工作的两个类能够子啊一起工作。
模式中的角色
目标接口(Target):客户所期待的接口。目标可以是具体的或抽象的类,也可以是接口。
需要适配的类(Adaptee):需要适配的类或适配者类。
适配器(Adapter):通过包装一个需要适配的对象,把原接口转换成目标接口。
实现方式主要有两种:
类的是适配器模式
对象适配器模式
1)类的是适配器模式
UML类图如图所示
类的适配器模式采用继承方式实现
Adaptee.java
package com.test.adapter;
public class Adaptee {
public void specificRequest() {
System.out.println("被适配类...的特异功能");
}
}
Target.java
package com.test.adapter;
public interface Target {
public void request();
}ConcreteTarget.java
package com.test.adapter;
public class ConcreteTarget implements Target{
@Override
public void request() {
// TODO Auto-generated method stub
System.out.println("普通类、、、没有特异功能");
}
}
Adapter.java
package com.test.adapter;
public class Adapter extends Adaptee implements Target{
@Override
public void request() {
// TODO Auto-generated method stub
super.specificRequest();
}
}
最后是客户端
Client.java
package com.test.adapter;
public class Client {
public static void main(String[] args) {
// 使用普通功能类
Target concreteTarget = new ConcreteTarget();
concreteTarget.request();
// 使用特殊功能类,即适配类
Target adapter = new Adapter();
adapter.request();
}
}
运行结果如下
普通类、、、没有特异功能
被适配类...的特异功能
2)对象适配器模式
UML类图如图所示
与类的适配器模式不同的是,对象的适配器模式不是使用继承关系连接到Adaptee类,而是使用代理关系连接到Adaotee类。
此时只需要修改Adapter.java
public class Adapter implements Target{
// 直接关联被适配类
private Adaptee adaptee;
// 可以通过构造函数传入具体需要适配的被适配类对象
public Adapter (Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public void request() {
// TODO Auto-generated method stub
adaptee.specificRequest();
}
}
客户端也要稍微修改一下
public class Client {
public static void main(String[] args) {
// 使用普通功能类
Target concreteTarget = new ConcreteTarget();
concreteTarget.request();
// 使用特殊功能类,即适配类
Target adapter = new Adapter(new Adaptee());
adapter.request();
}
}
只是new Adapter(new Adaptee());构造方法传入了新的参数,其它一样的,运行结果也是一样的。
从类图中我们也知道需要修改的只不过就是 Adapter 类的内部结构,即 Adapter 自身必须先拥有一个被适配类的对象,再把具体的特殊功能委托给这个对象来实现。使用对象适配器模式,可以使得 Adapter 类(适配类)根据传入的 Adaptee 对象达到适配多个不同被适配类的功能,当然,此时我们可以为多个被适配类提取出一个接口或抽象类。这样看起来的话,似乎对象适配器模式更加灵活一点。
总结
Adapter模式的经典实现在于将原本不兼容的接口融合在一起,使之能够很好的进行合作,但是在实际开发中,Adapter模式也有灵活的实现,可以稍微修改一下。例如ListView中的BaseAdapter,SimpleAdapter就稍微做了一下修改。
优点:
1)更好的复用性
2)更好的扩展性
缺点:
过多的使用适配器,会让系统凌乱,不易整体把握。
相关文章推荐
- iOS开发从入门到精通--开关按钮UISwitch控件
- 整理前段各种验证
- (高级篇)jQuery学习之jQuery Ajax用法详解
- UVa 471 - Magic Numbers
- PAT1010 一元多项式求导
- wi10优化
- Longest Substring Without Repeating Characters
- Qt基于FFmpeg播放本地 H.264(H264)文件
- adapter如何finish activity
- Android studio value 2 (com.android.dex.DexException:资源重复引用或者加载问题)
- pthread_mutex_t
- 在 Linux 上使用 VirtualBox 的命令行管理界面
- 大理石在哪?(Where is the Marble?,UVa 10474)
- 在 Linux 上使用 VirtualBox 的命令行管理界面
- dTree组件的学习
- Disruptor 详解
- C语言putenv()函数:改变或增加环境变量
- Java 的JSON、XML转换方法——目录索引
- org.apache.log4j.Logger 详解
- java 抽象类和接口区别