我们从它的名字中就可以清楚它的含义,这个模式呢,它直到一个适配器的作用。 那么什么是适配器呢?(请自行百度)
哈,开个玩笑,为了让大家认识一个适配器,来举个例子吧。众所周知,苹果在iPhone 7之后的手机产品(包括iPhone 7)就已经取消了3.5mm的耳机接口,而取代它的就是Lightning接口。那我们如果只有一个3.5mm的耳机,怎么去用新的iPhone手机听歌呢? 这时候,就需要适配器的帮忙。在这个例子里,我们也可以称它为转接头。
就是上面图片里的这个小家伙啦,它就是所谓的适配器,将一个接口,转换成用户期待的另一个接口。在这个实例中,我们将Lightning接口转换成我们期待的(也是将用到的)3.5mm的耳机接口。
上面已经清地讲解了适配器模式的原理,当我们想更深入地去了解它时,我们就要了解一个词:扩展。在我个人的理解中,这个扩展是适配器模式的核心思想,不急,我们来一步步,慢慢深入地了解适配器。
适配器分为三种,按理解的难易程度,分别为:接口适配器,类适配器,对象适配器。
在我们了解接口适配器之前,我们要先知道它是干嘛用的。简单地来说,就是当我们要实现某一个接口中的部分方法时,就得用这个接口适配器去实现它。这是为什么呢?我们直接实现类去实现这个接口不行吗? 这就涉及到我们对接口的基本概念有没有熟悉。当我们要定义一个类用implements关键字实现一个接口时,我们必须实现接口中的所有方法。但如果这个类为抽象类,我们可以只实现接口中的部分方法就行了。所以说,当这个接口中有我们不想使用到的方法,此时,我们就需要借助“接口适配器”来实现它了。
再来,我们看看接口适配器的UML图,让我们更好地去了解它的结构。
从图中可得知,我们有三个对象:
Human:我们定义的一个接口,其中有三个抽象方法。
Adapter:一个抽象类,在这个结构扮演者适配器的角色。
Child:一个实现类,它继承了Adapter,并实现了其中的eat()方法 和 sleep()方法。
下面我们来看看代码
Hunam接口:
public interface Human {
void eat();
void work();
void sleep();
}
Adapter适配器
public abstract class Adapter implements Human {
public void eat() {
}
public void work() {
}
public void sleep() {
}
}
Child实现类
public class Child extends Adapter {
@Override
public void eat() {
System.out.println("生下来就会吃喝");
}
@Override
public void sleep() {
System.out.println("生下来就会睡觉");
}
}
Text测试类
public class Text {
public static void main(String args[]) {
Human hz = new Child();
hz.eat();
hz.sleep();
}
}
最后运行结果:
生下来就会吃喝
生下来就会睡觉
接下来讲讲类的适配器
当我们的目标接口是A接口(不可以访问其它接口),可是A接口中并没有我们想要的方法,而B类中却有我们想要使用的方法时,我们就可以用适配器,将B类中的方法扩展到A接口中。
首先,我们还是先看看它的UML图:
它呢,同相拥有三个对象
A接口:我们的目标接口
B类:拥有我们想要的方法,是我们的目标类
Adapter类:作为适配器继承目标类B的同时,实现了接口A。
接口A
public interface A {
void eat();
void sleep();
void work();
}
目标类B
public class B{
public void work() {
System.out.println("学会了工作");
}
}
适配器Adapter
public class Adapter extends B implements A {
public void eat() {
}
public void sleep() {
}
}
测试类
public class text {
public static void main(String args[]) {
A a = new Adapter();
a.work();
}
}
最后运行结果:
学会了工作
最后我们讲讲对象适配器,在看对象适配器前,最好把类的适配器先理解了,再学习对象适配器就容易多了。
在类的适配器中呢,我们通过继承来实现方法的扩展而在对象适配器中,我们不通过继承了,而是通过持有目标类的实例来解决兼容性的问题。
所以我们只需要更改Adapter类的代码即可。
public class Adapter implements A {
private B b;
public Adapter(B b) {
this.b = b;
}
public void eat() {
}
public void work() {
b.work();
}
public void sleep() {
}
}
在这个代码块中,我们定义了一个私有的 B类参数b,然后通过Adapter的构造方法将其实例导入。这样子我们就在Adapter类中拥有了B的实例,可以运用这个实例对B中的方法进行调用。
public class text {
public static void main(String args[]) {
B b = new B(); //创建一个B的实例
A a = new Adapter(b); //通过Adapter的构造方法将其导入适配器中。
a.eat();
a.work();
a.sleep();
}
}
最后运行结果(与类适配器的运行结果相同):
学会了工作
到了这里,我们已经将适配器模式学会了。接下来,我们来总结一下学习的内容。
接口适配器:当我们想到实现接口中的部分方法时,我们可以创建一个适配器,然后通过继承这个适配器实现我们想要的方法。
类适配器:当我们 要实现的方法 的类 不是我们所期望的接口时,我们可以通过类适配器继承这个目标类并实现接口,就可以解决兼容问题。
对象适配器:当我们希望将一个对象转换成满足目标接口的新对象时,可以用适配器持有这个对象的实例,在适配器是调用实例中的方法即可。
可能这篇博文比较啰嗦,但为了可以更清晰地描述适配器模式还是不得不如此。最后希望大家能够学有所获,因水平有限,若有不尽之处望大家指出。