大家好,欢迎来到程序视点!从这篇文章开始,我们将着手结构型模式的分享。第一个要讲的就是适配器模式

引子

适配器,顾名思义,得适应当前的不同配置,解决兼容性问题。我们生活中充满了各种各样的适配器,比如上网用的“光猫”,就是光信号和电信号的互相转化。还有各种变压器也属于电压转换的适配器。如果觉得还不够形象可以看一下家里的电器,比如你的电视是两项插头,墙上的插孔是三项插孔怎么办?

哦,那我们需要的是一个转换器,用优雅微妙的方式化解这种不兼容情况。中间这个就是我们的适配器!

适配器模式简介

适配器模式,将某个类的接口转换成客户端期望的另一个接口表示,目的是消除由于接口不匹配所造成的类的兼容性问题。粗暴点的理解:通过适配器把一个类型变成目标类型适配器主要分为三类:类的适配器模式、对象的适配器模式、接口的适配器模式。我们一一来看。

类适配器模式

通过多重继承目标接口和被适配者类方式来实现适配。这里我们使用前面图中的两项插头适配到三项插孔为例。先是我们的目标接口(三项插孔):

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

欢迎关注程序视点,这里会不定时分享一些技术要点,更有一些深受资源收藏爱好者会喜欢的优质学习资料。吃瓜、摸鱼、白嫖技术就等你了~

如果该文章对你有帮助,那么就点击右下角的  [点赞]「在看」,给一个小小的鼓励吧

posted on 2024-01-11 15:12  程序视点  阅读(6)  评论(0编辑  收藏  举报