1. 适配器模式
1.1 定义
适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。
这种模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能。
1.2 介绍
适配器模式主要解决要将一些“现存的对象”放到新的环境中,而新的环境要求的接口是现对象不能满足的,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作
。适配器模式可分为对象适配器和类适配器和缺省适配器模式三种:
- 在对象适配器模式中,适配器与适配者之间是关联关系;
- 在类适配器模式中,适配器与适配者之间是继承(或实现)关系;
- 缺省适配器:当不需要实现一个接口所提供的所有方法时,可先设计一个抽象类实现该接口,并为接口中每个方法提供一个默认实现(空方法),那么该抽象类可以覆盖父类中的某些方法。
使用场景:有动机地修改一个正常运行的系统的接口,这时应该考虑使用适配器模式。
适配器模式可以分为一下角色
目标角色(Target):该角色定义将源角色转换为哪种接口,即满足新要求的接口;
源角色(Adaptee):该角色为已有接口,将哪个对象(类)转换为目标角色;
适配器角色(Adapter):通过继承或者关联的方式,将元觉得色转换为目标角色。
2. 代码介绍
1. 类适配器
//目标角色
public interface Target {
void show();
}
//源角色
public class Adaptee {
public void adapterShow(){
System.out.println("现有的对象,源角色");
}
}
//适配器角色
public class Adapter extends Adaptee implements Target {
@Override
public void show() {
super.adapterShow();
}
}
public class Test {
public static void main(String[] args) {
Target adapter = new Adapter();
adapter.show();
}
}
/**
* 现有的对象,源角色
*/
2. 对象适配器
对象适配器与类适配器相似,只有适配器类不同
public class Adapter implements Target {
private Adaptee adaptee = new Adaptee();
@Override
public void show() {
adaptee.adapterShow();
}
}
3. 缺省适配器
缺省适配器在对象适配器基础上修改,在接口多加了一些方法,方便测试,同时增加了一个类用于覆盖父类的某些方法。
public interface Target {
void show();
void eat();
void play();
}
public class Adaptee {
public void adapterShow(){
System.out.println("现有的对象,源角色");
}
}
public class AbstractClass implements Target{
@Override
public void show() {
}
@Override
public void eat() {
}
@Override
public void play() {
}
}
public class Adapter extends AbstractClass {
private Adaptee adaptee = new Adaptee();
@Override
public void show() {
adaptee.adapterShow();
}
}
public class Test {
public static void main(String[] args) {
Target adapter = new Adapter();
adapter.show();
}
}
/**
* 现有的对象,源角色
*/
JAVA JDK 1.1 提供了 Enumeration 接口,而在 1.2 中提供了 Iterator 接口,想要使用 1.2 的 JDK,则要将以前系统的 Enumeration 接口转化为 Iterator 接口,这时就需要适配器模式。
public class EnumerationIterator implements Iterator {
private Enumeration e;
public EnumerationIterator(Enumeration e) {
this.e = e;
}
public boolean hasNext() {
return this.e.hasMoreElements();
}
public Object next() {
return this.e.nextElement();
}
public void remove() {
throw new UnsupportedOperationException("remove() not supported by Enumeration");
}
}
步骤:
- 新增被适配的类,这里是要适配调Enumeration,所以增加类EnumerationAdapter;
- 新增类继承目标接口,这里的目标接口是Iterator,保持适配器和目标接口类型一致;
- 新增类继承持有被适配类的引用。
3. 适配器的优缺点
优点
- 可以让任何两个没有关联的类一起运行。
- 提高了类的复用。
- 增加了类的透明度。
- 灵活性好。
缺点
- 过多地使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是 A 接口,其实内部被适配成了 B 接口的实现,一个系统如果太多出现这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。
- 由于 JAVA 至多继承一个类,所以至多只能适配一个适配者类,而且目标类必须是抽象类。