适配器模式:把一个类的接口变成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的类能够在一起工作。
适配器模式分类:类适配器;对象适配器
类适配器:
涉及到的角色:1、目标角色:所起到得到的接口,目标为接口
2、源角色:需要适配的接口
3、适配器角色:适配器类把源接口转换为目标接口,这一角色必须是类
public interface Job {
public abstract void speakChinese();
public abstract void speakJapanese();
public abstract void speakFrench();
}
public class Person {
private String name;
private String sex;
private int age;
public void speakChinese(){
System.out.println("说中文");
}
public void speakJapanese(){
System.out.println("说英文");
}
}
public class Adapter extends Person implements Job{
@Override
public void speakFrench() {
System.out.println("说法语");
}
}
public class Test {
public static void main(String[] args) {
Adapter person = new Adapter();
person.speakChinese();
person.speakJapanese();
person.speakFrench();
}
}
对象适配器:把被适配的类的API转换为目标类的API,与类的适配器模式不同的是,对象的适配器模式不是使用继承关系连接到Adaptee类,而是使用委派关系连接到Adaptee类。
public interface Target {
public void request();
}
public class Adapte {
public void specialRequest(){
System.out.println("需要适配的类");
}
}
public class AdapterClass implements Target{
private Adapte adapte;
public AdapterClass(Adapte adapte){
this.adapte = adapte;
}
@Override
public void request() {
this.adapte.specialRequest();
}
public static void main(String[] args) {
AdapterClass adapterClass = new AdapterClass(new Adapte());
adapterClass.request();
AdapterObject object = new AdapterObject();
object.request();
object.specialRequest();
}
}
类适配器和对象适配器权衡:
1、类适配器使用对象继承的方式,是静态的定义方式;对象适配器使用对象组合的方式,是动态组合的方式
2、对于类适配器,由于适配器直接继承了Adaptee,使得适配器不能和Adaptee的子类一起工作,因为继承是静态的关系,当适配器继承了Adaptee后,就不可能再去处理Adaptee的子类了。
对于对象适配器,一个适配器可以把多种不同的源适配到同一个目标,换言之, 同一个适配器可以把源类和它的子类都适配到目标接口,因为对象适配器采用的是对象组合的关系, 只要对象类型正确,是不是子类都无所谓。
3、对于类适配器,适配器可以重定义Adaptee的部分行为,相当于子类覆盖父类的部分实现方法。
对于对象适配器,要重定义Adaptee的行为比较困难,这种情况下,需要定义Adaptee的子类来实现重定义,然后让适配器组合子类,虽然重定义Adaptee的行为比较困难,但要添加一些新的行为则很方便,而且新增加的行为可同时使用于所有的源。
4、对于类适配器,仅仅引入了一个对象,并不需要额外的引用来间接得到Adaptee
对于对象适配器,需要额外的引用来得到Adaptee。
建议尽量使用对象适配器的实现方式,所用合成/聚合,少用继承。
适配器模式的优点:
1、更好地复用性
系统需要使用现有的类,而此类的接口不符合系统的需要,那么通过适配器模式就可让这些功能得到更好的复用。
2、更好地扩展性
在实现适配器功能的同时,可以调用自己开发的功能,从而自然的扩展系统的功能。
适配器模式的缺点:
过多的使用适配器,会让系统非常零乱,不易整体进行把握,比如,明明看到调用的是A接口,其实内部被适配成了B接口的实现,一个系统如果太多出现这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。
缺省适配模式
缺省适配模式为一个接口提供缺省实现,这样子类型可以从这个缺省实现进行扩展,而不必从原有接口进行扩展,作为适配器模式的一个特例,缺省适配器模式在java语言中有着特殊的应用。
public interface Job {
public void speakChinese();
public void speakJapanese();
public void speakFrench();
public void speakEnglish();
}
public abstract class JobDefault implements Job{
@Override
public void speakChinese() {
}
@Override
public void speakJapanese() {
}
@Override
public void speakFrench() {
}
@Override
public void speakEnglish() {
}
}
public class JobImpl extends JobDefault{
public void speakChinese(){
System.out.println("说中文");
}
}