大家好,欢迎来到程序视点!从这篇文章开始,我们将着手结构型模式的分享。第一个要讲的就是适配器模式
。
引子
适配器,顾名思义,得适应当前的不同配置,解决兼容性问题。我们生活中充满了各种各样的适配器,比如上网用的“光猫”,就是光信号和电信号的互相转化。还有各种变压器也属于电压转换的适配器。如果觉得还不够形象可以看一下家里的电器,比如你的电视是两项插头,墙上的插孔是三项插孔怎么办?
哦,那我们需要的是一个转换器,用优雅微妙的方式化解这种不兼容情况。中间这个就是我们的适配器!
适配器模式简介
适配器模式,将某个类的接口转换成客户端期望的另一个接口表示,目的是消除由于接口不匹配所造成的类的兼容性问题。粗暴点的理解:通过适配器把一个类型变成目标类型
适配器主要分为三类:类的适配器模式、对象的适配器模式、接口的适配器模式。我们一一来看。
类适配器模式
通过多重继承目标接口和被适配者类方式来实现适配。这里我们使用前面图中的两项插头适配到三项插孔为例。先是我们的目标接口(三项插孔):
public interface TriplePin {
//参数分别为火线live,零线null,地线earth
public void electrify(int l, int n, int e);
}
被适配者类的接口(两项插孔)
public interface DualPin {
public void electrify(int l, int n);//这里没有地线
}
一个被适配者类(这是两项插孔的一个具体实现),我们用电视机作为例子:
public class TV implements DualPin {
@Override//既然是两项插头,当然实现两项插标准
public void electrify(int l, int n) {
System.out.println("火线通电:" + l);
System.out.println("零线通电:" + n);
}
}
那么问题来了,墙上的接口是三插标准,电视实现的是两插标准,无法通电。怎么办?这就需要个适配器类啊!
public class AdapterDual2Triple extends TV implements TriplePin{
@Override
public void electrify(int l, int n, int e) {
super.electrify(l, n);
}
}
这个 AdapterDual2Triple 解决两项和三项插孔之间不可调和的矛盾。AdapterDual2Triple 继承了 TV类,就获得了接入两项插孔的功能;接着实现 TriplePin 接口,重写三项插孔接口的功能,表示它就是一个能接入三项插孔的类型。
对象的适配器模式
对象适配器和类适配器使用了不同的方法实现适配,对象适配器使用组合,类适配器使用继承
。
public class AdapterDual2Triple implements TriplePin{
DualPin tv = new TV();
@Override
public void electrify(int l, int n, int e) {
tv.electrify(l, n);
}
}
这里直接就指定了一个TV对象。适配器看着是接入了三项插孔,但实际上是TV对象干的两项插孔的活。反过来说,就是两项的TV对象适配到了三项的插孔上了。
接口的适配器模式
这个模式主要适用于目标接口有很多抽象方法,而我们不想使用其全部方法的情况。假设三项插头除了通电外,还有其他功能a()、b()、c()等。
public interface TriplePin {
//参数分别为火线live,零线null,地线earth
public void electrify(int l, int n, int e);
void a();
void b();
void c();
}
我们借助中间抽象类空实现目标接口所有方法,子类选择性重写,可以减少实现不必要方法。中间抽象层:
public class TripleAdaptor implements TriplePin {
//参数分别为火线live,零线null,地线earth
public void electrify(int l, int n, int e) {}
void a() {}
void b() {}
void c() {}
}
现在我们的 TV对象 只需要三项插孔接口中接线的功能;
public class AdapterDual2Triple extends TripleAdaptor{
DualPin tv = new TV();
@Override
public void electrify(int l, int n, int e) {
tv.electrify(l, n);
}
}
OK,我们只需要重写一个方法即可。
总结
我们一起来看下三种适配器模式的应用场景:
- 类适配器模式:当希望将一个类转换成满足另一个新接口的类时,可以使用类的适配器模式,创建一个新类,继承原有的类,实现新的接口即可。
- 对象适配器模式:当希望将一个对象转换成满足另一个新接口的对象时,可以创建一个Wrapper类,持有原类的一个实例,在Wrapper类的方法中,调用实例的方法就行。
- 接口适配器模式:当不希望实现一个接口中所有的方法时,可以创建一个抽象类Wrapper,实现所有方法,我们写别的类的时候,继承抽象类即可。
记住适配器模式的特点:可以让任何两个没有关联的类一起运行_PS:这个特点可以很好的用于区分后面要讲的代理模式_同时,这个特点也容易导致一个问题:由于任何不相关的类都能融合在一起使用,当过多的使用这个模式,系统中各个类都相互关联,耦合度增加,系统会变得凌乱不堪。因此,尽量在碰到无法改变原有设计和代码的情况下,才考虑使用适配器模式。
One more thing
欢迎关注程序视点,这里会不定时分享一些技术要点,更有一些深受资源收藏爱好者会喜欢的优质学习资料。吃瓜、摸鱼、白嫖技术就等你了~
如果该文章对你有帮助,那么就点击右下角的 [点赞]「在看」,给一个小小的鼓励吧