适配器模式
定义:适配器你可以看作是一个中间件,对于不匹配的两个东西进行匹配,就像转换器或者转接头一样。举个例子,比如你的电源插座只有两相插座,但是你的笔记本需要三相插座,那怎么办?不匹配啊,你插不进去的,这个时候,你会去找一个三相转两相的转接器,这样就可以用来。所以,适配器的功能就是做两头的转换。
使用场景:
(1)想要使用一个已经存在的类,但是它却不符合现有的接口规范,导致无法直接去访问,这时创建一个适配器就能间接去访问这个类中的方法。
(2)我们有一个类,想将其设计为可重用的类(可已经被多处访问了),我们可以创建适配器来将这个类来适配其他没有提供合适接口的类。
(3)想要使用接口中的某个或者某些方法,但是接口中有太多不是自己需要的方法了,接口在实现时必须实现其中的所有方法,这个时候就要使用抽象类来实现接口,并不对所有方法进行实现(进置空),然后我们再继承这个抽象类来重写想要的方法。这个抽象类就是适配器。
你可能并不明白上述这些场景是如何实现的,下面我会用实例来告诉你:
适配器模式实现的方式有三种:类适配器,对象适配器,接口适配器。
1、类适配器——通过继承来实现适配功能
问题描述:我们要访问的接口A,其中缺了一个我门需要的方法,但是在接口B中发现了这个方法,但是我们不能改变访问接口A,在这种情况下,我们可以定义一个适配器C来进行中转,这个适配器C需要实现我们访问的接口A(这样我们就能访问到A中的方法),同时继承B接口的实现类BB(这样就可以在适配器C中访问接口B的方法啦)。类实现接口A和继承B的实现类来达到我们想要的功能,这个类就是适配器类:
public class AdapterDemo {
public static void main(String[] args) {
Ps2 p = new Adapter();
p.isPs2();
}
}
interface Ps2 {
void isPs2();
}
interface Usb {
void isUsb();
}
class Usber implements Usb {
@Override
public void isUsb() {
System.out.println("USB口");
}
}
class Adapter extends Usber implements Ps2 {
@Override
public void isPs2() {
isUsb();
}
}
输出结果:USB口
这里讲解一下:
我手中有个ps2插头的设备,但是主机上只有usb插头的插口,怎么办呢?弄个转换器,将ps2插头转换成为USB插头就可以使用了。
接口Ps2:描述ps2接口格式
接口Usb:描述USB接口格式
类Usber:是接口Usb的实现类,是具体的USB接口格式
Adapter:用于将ps2接口格式转换成为USB接口格式
2、对象适配器模式——通过组合来实现适配器功能
当我们要访问的接口A中没有我们想要的方法,却在另一个接口B中发现了合适的方法,我们又不能改变访问接口A,在这种情况下,我们可以定义一个适配器P来进行中转,这个适配器P要实现我们访问的接口A,这样我们就能继续访问当前接口A中的方法(虽然他目前不是我们要的),然后在适配器P中定义私有变量C(对象)(B接口指向的变量名),再定义一个带参数的构造器用来为对象C赋值,再在A接口的方法实现中使用对象C调用其来源于B接口的方法。
看一下例子:
public class AdapterDemo {
public static void main(String[] args) {
Ps2 p = new Adapter(new Usber());
p.isPs2();
}
}
interface Ps2 {
void isPs2();
}
interface Usb {
void isUsb();
}
class Usber implements Usb {
@Override
public void isUsb() {
System.out.println("USB口");
}
}
class Adapter extends Usber implements Ps2 {
private Usb usb;
public Adapter(Usb usb) {
this.usb = usb;
}
@Override
public void isPs2() {
usb.isUsb();
}
}
结果:USB口
跟上一种模式很类似,我觉得就没必要讲了吧,说白了就是用对象来调用方法,其实是一样的
3、接口适配器模式——通过抽象类来实现适配,这种适配有别于上述的适配
当存在这样一个接口,其中定义了很多很多方法,而我们现在却只想使用其中的一个到几个方法,如果我们直接实现接口,那么我们要对所有的方法进行实现,就算我们对不需要的方法进行置空(只写一对大括号,不作具体方法实现)也会导致着这个类变得臃肿,调用不便,这是我们可以使用一个抽象类作为中间件即适配器,用这个抽象类实现接口,而在抽象类中所有方法都进行置空,那么我们在创建抽象类的继承类,而且只重写我们需要使用的那几个方法就行。
代码如下:
public class AdapterDemo {
public static void main(String[] args) {
A a = new AdapterTest();
a.a();
a.d();
}
}
interface A {
void a();
void b();
void c();
void d();
void e();
void f();
}
abstract class Adapter implements A {
public void a() {}
public void b() {}
public void c() {}
public void d() {}
public void e() {}
public void f() {}
}
class AdapterTest extends Adapter {
public void a() {
System.out.println("实现A方法被调用");
}
public void d() {
System.out.println("实现d方法被调用");
}
}
结果:
实现A方法被调用