关于java:无处不在的适配器模式

8次阅读

共计 3924 个字符,预计需要花费 10 分钟才能阅读完成。

0x01:适配器模式简介

对于适配器置信不会生疏,生存中的例子亘古未有,像耳机转接线,充电器适配器,水管适配接口等等。通过类比很容易了解软件中的适配器模式。

客户端须要一个 target(指标)接口,然而不能间接重用曾经存在的 adaptee(适配者)类,因为它的接口和 target 接口不统一,所以须要 adapter(适配器)将 adaptee 转换为 target 接口。前提是 target 接口和已存在的适配者 adaptee 类所做的事件是雷同或类似,只是接口不同且都不易批改。如果在设计之初,最好不要思考这种设计模式。凡事都有例外,就是设计新零碎的时候思考应用第三方组件,因为没必要为了投合第三方组件批改本人的软件设计格调,能够尝试应用适配器模式。

上面是一个十分典型的应用适配器模式的场景:

Sun 公司在 1996 年公开了 Java 语言的数据库连贯工具 JDBC,JDBC 使得 Java 语言程序可能与数据库连贯,并应用 SQL 语言来查问和操作数据。JDBC 给出一个客户端通用的形象接口,每一个具体数据库厂商(如 SQL Server、Oracle、MySQL 等)的 JDBC 驱动软件都是一个介于 JDBC 接口和数据库引擎接口之间的适配器软件。形象的 JDBC 接口和各个数据库引擎 API 之间都须要相应的适配器软件,这就是为各个不同数据库引擎筹备的驱动程序。

另外一个比拟典型的适配器场景 J2EE 标准与 J2EE 标准实现的服务器。SUN 公司提供了一套 J2EE 标准,而后不同厂商依据本人的了解实现了不同的应用服务器。SUN 公司提供了一套 servlet api 标准,而后实现这套标准的驰名应用服务器有 Apache Tomcat、Jetty、Oracle 的 Weblogic、IBM 的 WebSphere 等。

适配器模式的 UML 类图如下

从类图上看次要蕴含如下角色:

  • 指标角色(target):这是客户所期待的接口。指标能够是具体的或形象的类,也能够是接口;
  • 适配者角色(adaptee):已存在接口(能够了解是第三方提供的接口),然而和客户端期待的接口不兼容;
  • 适配器角色(adapter):将已有接口转换成指标接口(能够了解我方须要的接口);

0x02:适配器模式的实现

类适配器模式(class adapter pattern)
通过继承进行适配(类间继承)。类适配器模式在编译时实现 target(指标)接口。这种适配器模式应用了多个实现了期待的接口或者曾经存在的接口的多态接口。比拟典型的就是:target 接口被创立为一个纯正的接口,Java 不反对多继承的语言。

Target:Target 指标角色,该角色定义把其余类转换为何种接口,也就是冀望接口,通常状况下是一个接口或一个抽象类,个别不会是实现类

public interface Target {public void request();

}

Adaptee:Adaptee 源角色,想把谁转换为指标角色,这个“谁”就是源角色,它是曾经存在的、运行良好的类或对象

public class Adaptee {public void specificRequest() {System.out.println("我是曾经存在的运行良好的第三方厂商");
    }

}

Adapter:Adapter 适配器角色,是适配器模式的外围角色,它的职责是通过继承或是类关联的形式把源角色转换为指标角色

public class Adapter extends Adaptee implements Target {

    @Override
    public void request() {super.specificRequest();
    }

}

ConcreteTarget:指标角色的实现类

public class ConcreteTarget implements Target {

    @Override
    public void request() {System.out.println("没有减少适配器的我方一般实现逻辑");
    }

}

类适配器模式测试代码

public class Client {public static void main(String[] args) {
        // 原有无适配器的业务逻辑
        Target target = new ConcreteTarget();
        target.request();

        // 减少适配器后的业务逻辑
        Target target2 = new Adapter();
        target2.request();}

}

对象适配器模式(object adapter pattern)
通过对象档次的关联关系进行委托(对象的合成关系 / 关联关系)。对象适配器模式在运行时实现 target(指标)接口。在这种适配器模式中,适配器包装了一个类实例。在这种状况下,适配器调用包装对象实例的办法。

Target:客户所期待的接口。指标能够是具体的或形象的类,也能够是接口

public class Target {public void request() {System.out.println("没有适配器的一般申请");
    }

}

Adaptee:须要适配的类

public class Adaptee {public void specificRequest() {System.out.println("适配器类实现的非凡申请");
    }

}

Adapter:通过在外部包装一个 Adaptee 对象,把源接口转换成指标接口

public class Adapter extends Target {private Adaptee adaptee = new Adaptee();

    @Override
    public void request() {
        // 替换原理的逻辑,调用适配类的逻辑
        adaptee.specificRequest();}
}

对象适配器模式测试代码

public class Client {public static void main(String[] args) {Target target = new Adapter();
        target.request();}

}

缺省适配器模式(default adapter pattern),也叫默认适配器模式、接口适配器模式
当不须要全副实现接口提供的办法时,能够设计一个适配器抽象类实现接口,并为接口中的每个办法提供默认办法实现或者空实现(如果大家做过 GUI 编程,就能够常常遇到这种实现,特地是各种控件的事件监听都提供了适配器类),抽象类的子类就能够有抉择的笼罩父类的某些办法实现需求,它实用于一个接口不想应用所有的办法的状况。在 java8 后,接口中能够有 default 办法,就不须要这种缺省适配器模式了。接口中办法都设置为 default,实现为空,这样同样同样能够达到缺省适配器模式同样的成果。

target:蕴含了很多没有实现的操作接口

public interface Target {public abstract void operation1();

     public abstract void operation2();

     public abstract void operation3();}

Adapter:默认实现了所有操作抽象类,只是所有的实现都是空实现

public abstract class DefaultAdapter implements Target{

    @Override
    public void operation1() {}

    @Override
    public void operation2() {}

    @Override
    public void operation3() {}

}

测试缺省适配器模式须要用到的类(相当于 GUI 编程的一个组件,比方按钮 Button)

public class Operator {
    private Target target;

    public void addOperation(Target target) {this.target= target;}

    public void operation1() {target.operation1();
    }

    public void operation2() {target.operation2();
    }

    public void operation3() {target.operation3();
    }
}

缺省适配器模式测试代码

public class Client{public static void main(String[] args) {
        // 原来要实现所有操作类的操作
        Operator operator1= new Operator();
        operator1.addOperation(new Target() {
            @Override
            public void operation1() {}

            @Override
            public void operation2() {System.out.println("invoke operation2");
            }

            @Override
            public void operation3() {}

        });
        operator1.operation2();

        // 2、应用缺省适配器只须要实现须要用到的接口办法
        Operator operator2 = new Operator();
        operator2.addOperation(new DefaultAdapter() {
            @Override
            public void operation2() {System.out.println("invoke operation2");
            }
        });
        operator2.operation2();}
}

适配器模式实质上是现有的不兼容的接口转换为须要的接口。类适配器模式以继承现有类的形式转换;对象适配器模式以聚合对象实例的形式转换;接口适配器模式以实现接口的形式转换。适配器模式是在现有的类和零碎都不易批改的状况下才应用,在零碎设计之初慎用该设计模式。

正文完
 0