百度工程师教你玩转设计模式(适配器模式)

作者 | 北极星小组

在现实生活中,经常会遇到两个“方针” 因为接口不兼容而不能一起作业的场景,这时需求第三者进行适配,如:国内的充电线插头不一定适用国外的插座需求凭借转接头、SD卡无法直接链接电脑需求凭借读卡器、用直流电的笔记本电脑接交流电源时需求一个电源适配器等。

软件设计中,需求开发的具有某种事务功用的组件在现有的组件库中现已存在,但它们与当时体系的接口规范不兼容,假如重新开发这些组件成本又很高,这时用适配器形式能很好地解决这些问题。

适配器形式(Adapter Pattern):是指将某个类的接口转化成客户端希望的另一个接口,主要意图是兼容性,让原本因接口不匹配不能作业的两个类能够协同作业。

百度工程师教你玩转设计模式(适配器模式)

△适配器示意图

适配器形式包含如下人物:

  • Target:方针笼统类, 界说客户要运用的接口

  • Adapter:适配器类,将Adaptee的接口进行适配转化

  • Adaptee:适配者类,需求被转化接口的方针

  • Client:客户类,经过适配器接口Target去运用Adaptee的功用

百度工程师教你玩转设计模式(适配器模式)

△方针适配器

百度工程师教你玩转设计模式(适配器模式)

△类适配器

一、适配器形式在文档事务场景中的运用(方针适配器)

微软office文档有两种数据格式,即office2007(OOXML格式)和Office2003(二进制格式)。在新事务场景中,因现有体系现已具有Office2007文档处理功用组件(数据、阅读器等),现在需求在此基础上扩大支持office2003格式的文档。即复用现有的office2007组件类,但接口与复用环境要求不一致,此刻能够运用适配器形式。

示例运用方针适配器办法,疏忽事务处理细节,仅做流程上的笼统来表明适配器形式的运用,根据形式结构笼统出各个人物类:

  • Doc2003方针笼统类

  • Doc2007适配者类

  • DocAdapter适配器类

  • Document客户类

// Document客户类运用方
public class Document {
  public void View(Doc2003 doc) {
    doc.show()
  }
}
// Doc2003接口笼统
public interface IDoc2003 {
    void show();
}
// Doc2007适配者类
public class Doc2007 {
    public void show() {
        System.out.println("office2007标准处理流程");
    }
}
// DocAdapter适配器类
public class DocAdapter implements IDoc2003 {
    private Doc2007 doc2007;
    public DocAdapter(Doc2007 doc2007){
        this.doc2007 = doc2007;
    }
    @Override
    public void show() {
        System.out.println("适配器:这里省掉了适配到2007的一堆适配逻辑...");
        doc2007.show();
    }
}
// 测验类
public class Test {
  public static void main(String[] args) {
    Document document = new Document();
    Doc2003  doc2003 = new DocAdapter(new Doc2007()) ; 
    document.view(doc2003);
  }
}

二、适配器形式在替换依靠组件场景中的运用(类适配器)

在实践的研发进程中,我们经常会需求对依靠组件进行更新迭代。在替换时,相关调用代码,往往散布在非常多的地方,而且因为调用办法与参数不一致,逐个修正作业量大,且存在遗失危险,这时候能够运用类适配器,将接口统一,减少相关代码的改动。

示例运用类适配器办法,疏忽事务处理细节,仅做流程上的笼统来表明适配器形式的运用,根据形式结构笼统出各个人物类:

  • AHandler方针笼统类

  • BHandler适配者类

  • BAdapter适配器类

  • Client客户类

//原依靠库-方针笼统类
public class AHandler {
    public void operation() {}
}
//新依靠库-适配者类
public class BHandler {
    public void action() {}
}
//适配器类
public class BAdapter extends BHandler {
    public void operation() {
        ...
        super.action();
        ...
    }
}
//客户类
public class Client {
    public static void main(String[] args) {
        //原调用
        AHandler aHandler = new AHandler();
        aHandler.operation();
        //新调用
        BAdapter bAdapter = new BAdapter();
        bAdapter.operation();
    }
}

三、适配器形式在接口完结场景的运用(接口适配器)

在实践的开发进程中,一个接口有很多的办法,可是对应的不同类只需求重视部分办法,其他无关的办法全都完结过于繁琐,尤其是涉及的完结类过多的状况。

例如,现有一个需求的方针接口方针Target,界说了很多相关的办法。可是在实践运用进程只需分别重视其间部分办法,而不是悉数完结。在此场景中:

被依靠的方针方针:TargetObj

适配器:Adapter

客户端:Client

// 方针方针:界说了很多的相关办法
public interface TargetObj {
    void operation1();
    void operation2();
    void operation3();
    void operation4();
    void operation5();
}
// 适配器:将方针接口界说的办法悉数做默认完结
public abstract class Adapter implements TargetObj {
    void operation1(){}
    void operation2(){}
    void operation3(){}
    void operation4(){}
    void operation5(){}
}
// 客户端:选用匿名内部类的办法完结需求的接口即可完结适配
public class Client {
    public static void main(String[] args) {
        Adapter adapter1 = new Adapter() {
            @Override
            public void operation3() {
            // 只是完结需求重视的办法即可
            System.out.println("operation3")
            }
        }
        Adapter adapter2 = new Adapter() {
            @Override
            public void operation5() {
            // 只是完结需求重视的办法即可
            System.out.println("operation5")
            }
        }
        adapter1.operation3();
        adapter2.operation5();
    }
}

四、总结

以上介绍了三种运用适配器形式的场景,适配器形式本质上是将现有的不兼容的接口转化为需求的接口,不需求改变本来的代码结构即可完结新的功用,通常完结办法上有:

  1. 方针适配器:经过方针的组合来达到适配意图;

  2. 类适配器:经过类的继承或许接口的完结来达到适配意图;

  3. 接口适配器:经过完结接口的办法转化来达到适配的意图;

适配器形式是在现有的类和体系都不易修正的状况下运用,在体系设计之初慎用适配器形式,这样会导致代码可读性变差,不易维护。

———- END ———-

引荐阅读【技能加油站】系列:

揭秘百度智能测验在测验评估领域实践

百度工程师带你探秘C++内存办理(理论篇)

从零到一了解APP速度测评

百度工程师教你玩转设计形式(工厂形式)

揭秘百度智能测验在测验剖析领域实践

百度用户产品流批一体的实时数仓实践

百度工程师教你玩转设计模式(适配器模式)