什么是适配器模式?
适配器模式是一种结构型设计模式。适配器模式是:当接口无法和类匹配到一起工作时,通过适配器将接口变换成可以和类匹配到一起的接口。
打个比喻:有一个电器的插头是三脚的,而现有的插座是两孔的,要使插头插上插座,我们需要一个插头转换器,这个转换器即是适配器。
源(Adaptee):需要被适配的对象或类型,相当于插头。
适配器(Adapter):连接目标和源的中间对象,相当于插头转换器。
目标(Target):期待得到的目标,相当于插座。
这是我们原来存在的代码
class Adaptee{
public void method1(){
System.out.println("这是原来的类,里面存在method1");
}
}
这是客户需要的目标接口
interface Target{
public void method1();
public void method2();
}
很显然原来的类无法满足客户的需求,这时候就需要一个适配器来让两者相匹配。
(之前我会不懂,为什么不在原来的类上去修改?因为原来的类被用了这么久,肯定是正确的,你在原来的类上修改,当类里面的代码很多,不容易维护。建一个适配器就很容易定位到错误在哪里)
适配器模式分类:
类适配器模式:类适配器使用的是继承的方式,一般来说无法对其子类进行适配
对象适配器模式:对象适配器使用的是组合的方式,子孙类都可以被适配。另外,对象适配器对于增加一些新行为非常方便,而且新增加的行为同时适用于所有的源。
接口适配器模式(又称缺省适配器模式):接口适配器模式(缺省适配模式)基本思想是,为一个接口提供缺省实现,这样子类可以从这个缺省实现进行扩展,而不必从原有接口进行扩展。
举例:
类适配器模式,从名字可以看出来直接和类相关,通过继承类,实现接口来达到需求。由于是继承的方式来得到适配器类,所以无法再对其子类进行适配。
class Adaptee{//源码
public void method1(){
System.out.println("这是原来的类,里面存在method1");
}
}
interface Target{//目标接口
public void method1();
public void method2();
}
class Adapter extends Adaptee implements Target{//适配器类
@Override
public void method2() {
System.out.println("这是接口中的方法。");
}
}
现在我们来测试一下适配器
public class Test {
public static void main(String[] args) {
Target adapter = new Adapter();
adapter.method1();
adapter.method2();
}
}
输出:
这是原来的类,里面存在method1
这是接口中的方法。
对象适配器模式:根据文字来看,肯定是与对象有关。对象适配器用的是组合的方式,将原有的类作为适配器的属性。组合方式来得到的适配器,可以对原有类的子类进行适配,将它作为属性加入就可以了。
interface Target{//目标接口
public void method1();
public void method2();
}
class Adapter implements Target{
Adaptee adaptee = new Adaptee();
@Override
public void method1() {
adaptee.method1();
}
@Override
public void method2() {
System.out.println("这是接口中的方法。");
}
}
测试
public class Test {
public static void main(String[] args) {
Target adapter = new Adapter();
adapter.method1();
adapter.method2();
}
}
输出
这是原来的类,里面存在method1
这是接口中的方法。
接口适配器模式(缺省适配模式)
接口适配器模式与上面的有些区别,接口适配器注重于接口中用不到的抽象太多,全多实现的话没有意义。
interface Target{//目标接口
public void method1();
public void method2();
public void method3();
}
abstract class abstractAdaptee implements Target{//定义一个抽象类,来选择需要重写的类
public void method1(){
System.out.println("默认实现");
}
public abstract void method2();//这个方法必须由子类来重写
public void method3(){
System.out.println("默认实现2");
}
}
//定义一个类来继承abstractAdaptee类
//通过接口和抽象类的结合,我们在子类中可以选择性的去实现那些抽象方法
class Adapter extends abstractAdaptee{//
@Override
public void method2() {
System.out.println("子类必须重写这个方法");
}
}
适配器的优点与缺点:
优点:复用性更强,对于那些和目标接口差别不是很大的类,通过适配器可以让这些类达到很好的复用,减少代码的书写。并且在适配中可以添加一些方法来扩展系统的功能,扩展性更好
缺点:用多了会让系统看起来杂乱无章。比如:明明调用的是接口A,结构里面的内容以及被修改成了接口B。一般建议直接对系统进行重构。