设计模式 | 适配器模式
介绍
适配器模式,重点在于 适配 两字,在两个没法直接交互的模块之间,插入一层,来处理他们交互的细节。
在编程中,一个经典的说法,如果一个系统没法做到通用,那就给他抽象出一层,把变化的东西封装进去
情景复现
考虑这么一个情况,我们有一台设备,供电端是 2 脚插头,恰巧发现客户现场提供有供电的插座,但可惜的却是 3 脚插座,我们可以和客户沟通请求帮忙
那么,考虑另一种情况,我们手里已经完成的系统 A,需要第三方的提供的数据接口,第三方已经提供了标准的 api,此时不太合适迁就我们进行调整;而我们的系统,设计的交口接口已经应用于其他地方,为了这个第三方 api 来编写特例情况,又不太合适
上面的情况总结起来,就是两方相互需要,但是对接的部分没法像齿轮一样紧紧的扣在一起协同工作,需要添加一个 中间层
来使他们正常的工作起来,这也就是适配器模式的由来
适配器模式的实现方式
先定义客户端,客户端使用的接口类,以及我们需要适配的 Adapee.class
。 我们在编写 client 调用 Target
接口时,发现有手里有一个类 Adapee
基本满足要求,只是需要为其做一点的适配
interface Target {
void targetMethod1();
}
class Adaptee {
void methodA() {}
}
class Client {
void func(Target target) {
target.targetMethod1();
}
}
继承被适配的类
如图,我们编写一个适配类,实现Target
接口,然后继承需要被适配的类,在 targetMethod1()
中调用继承的父类中的 methodA()
,并做一些适配,代码如下
class Adapter extends Adaptee implements Target {
@Override
public void targetMethod1() {
methodA();
// ....
}
}
组合被适配的类
在这个设计模式中,核心就是使用一个类上的功能,上一项是直接继承,我们就拥有了被适配的类的全部方法。我们也可以通过组合的方式来达到通用的效果,源码如下
class Adapter2 implements Target{
Adaptee adaptee;
@Override
public void targetMethod1() {
adaptee.methodA();
// ...
}
public void setAdaptee(Adaptee adaptee) {
this.adaptee = adaptee;
}
}
两种实现的比较
相同点:都能够将类适配为我们需要的样子
但是,我个人更加推荐使用组合
通过继承的方式,使的我们编写的类,与被适配的类,产生了 is a
的关系,但逻辑上并不一定存在这种继承关系。并且,由于 java 的单根继承特性,这会占用我们宝贵的继承名额
至于组合的缺点,大概就是需要我们显示的管理一下被适配的类的实例
转载自:https://juejin.cn/post/7001674812963684359