Android 设计模式--07:适配器模式(Adapter P

2023-12-30  本文已影响0人  DarcyZhou

本文转载自:Carson带你学设计模式:适配器模式(Adapter Pattern)

目录

设计模式7-1.PNG

1.介绍

1.1 定义

  适配器模式,即定义一个包装类,用于包装不兼容接口的对象。

包装类 = 适配器Adapter;
被包装对象 = 适配者Adaptee = 被适配的类。

1.2 主要作用

  把一个类的接口变换成客户端所期待的另一种接口,从而使原本接口不匹配而无法一起工作的两个类能够在一起工作。

适配器模式的形式分为:类的适配器模式和对象的适配器模式。

1.3 解决的问题

  原本由于接口不兼容而不能一起工作的那些类可以在一起工作。

2.模式原理

2.1 类的适配器模式

  类的适配器模式是把适配的类的API转换成为目标类的API。

2.1.1 UML类图 & 组成

设计模式7-2.PNG

在上图中可以看出:

Adapter与Adaptee是继承关系,这决定了这个适配器模式是类的。

2.1.2 使用步骤(代码解析)

步骤1: 创建Target接口;

public interface Target {

    //这是源类Adapteee没有的方法
    public void Request();  // 目标接口,期待得到的接口
}

步骤2: 创建源类(Adaptee) ;

public class Adaptee {

    public void SpecificRequest(){ // 需要适配的接口
    }
}

步骤3: 创建适配器类(Adapter);

//适配器Adapter继承自Adaptee,同时又实现了目标(Target)接口。
public class Adapter extends Adaptee implements Target {

    //目标接口要求调用Request()这个方法名,但源类Adaptee没有方法Request()
    //因此适配器补充上这个方法名
    //但实际上Request()只是调用源类Adaptee的SpecificRequest()方法的内容
    //所以适配器只是将SpecificRequest()方法作了一层封装,封装成Target可以调用的Request()而已
    @Override
    public void Request() {
        this.SpecificRequest();
    }

}

步骤4:定义具体使用目标类,并通过Adapter类调用所需要的方法从而实现目标。

public class AdapterPattern {

    public static void main(String[] args){

        Target mAdapter = new Adapter();
        mAdapter.Request();
    }
}

2.1.3 实例讲解

  接下来用一个实例来对类的适配器模式进行更深一步的介绍。

(1)实例概况

即适配器模式中的类的适配器模式。

(2)使用步骤

步骤1: 创建Target接口(期待得到的插头):能输出110V(将220V转换成110V);

 public interface Target {

    //将220V转换输出110V(原有插头(Adaptee)没有的)
    public void Convert_110v(); // 期待得到的插头
}

步骤2: 创建源类(原有的插头) ;

class PowerPort220V{
    //原有插头只能输出220V
    public void Output_220v(){
    }
}

步骤3:创建适配器类(Adapter);

class Adapter220V extends PowerPort220V implements Target{
    //期待的插头要求调用Convert_110v(),但原有插头没有
    //因此适配器补充上这个方法名
    //但实际上Convert_110v()只是调用原有插头的Output_220v()方法的内容
    //所以适配器只是将Output_220v()作了一层封装,封装成Target可以调用的Convert_110v()而已

    @Override
    public void Convert_110v(){
      this.Output_220v();
    }
}

步骤4:定义具体使用目标类,并通过Adapter类调用所需要的方法从而实现目标(不需要通过原有插头)

//进口机器类
class ImportedMachine {

    @Override
    public void Work() {
        System.out.println("进口机器正常运行");
    }
}

//通过Adapter类从而调用所需要的方法
public class AdapterPattern {
    public static void main(String[] args){

        Target mAdapter220V = new Adapter220V();
        ImportedMachine mImportedMachine = new ImportedMachine();

        //用户拿着进口机器插上适配器(调用Convert_110v()方法)
        //再将适配器插上原有插头(Convert_110v()方法内部调用Output_220v()方法输出220V)
        //适配器只是个外壳,对外提供110V,但本质还是220V进行供电
        mAdapter220V.Convert_110v();
        mImportedMachine.Work();
    }
}

2.2 对象的适配器模式

  与类的适配器模式相同,对象的适配器模式也是把适配的类的API转换成为目标类的API。

与类的适配器模式不同的是,对象的适配器模式不是使用继承关系连接到Adaptee类,而是使用委派关系连接到Adaptee类。

2.2.1 UML类图

设计模式7-3.png

在上图中可以看出:

Adapter与Adaptee是委派关系,这决定了适配器模式是对象的。

2.2.2 使用步骤(代码解析)

步骤1: 创建Target接口;

public interface Target {

    //这是源类Adapteee没有的方法
    public void Request();  // 期待得到的接口
}

步骤2: 创建源类(Adaptee) ;

public class Adaptee {

    public void SpecificRequest(){
    }
}

步骤3: 创建适配器类(Adapter)(不适用继承而是委派);

class Adapter implements Target{  
    // 直接关联被适配类  
    private Adaptee adaptee;  

    // 可以通过构造函数传入具体需要适配的被适配类对象  
    public Adapter (Adaptee adaptee) {  
        this.adaptee = adaptee;  
    }  

    @Override
    public void Request() {  
        // 这里是使用委托的方式完成特殊功能  
        this.adaptee.SpecificRequest();  
    }  
}  

步骤4:定义具体使用目标类,并通过Adapter类调用所需要的方法从而实现目标;

public class AdapterPattern {
    public static void main(String[] args){
        //需要先创建一个被适配类的对象作为参数  
        Target mAdapter = new Adapter(new Adaptee());
        mAdapter.Request();
    }
}

在这里就不再举实例进行讲解了(详情请看上面“进口机器的插头”),只是在适配类实现时将“继承”改成“在内部委派Adaptee类”而已。

3.优缺点

3.1 适配器模式

(1)优点

  系统需要使用现有的类,而此类的接口不符合系统的需要。那么通过适配器模式就可以让这些功能得到更好的复用。

  客户端可以调用同一接口,因而对客户端来说是透明的。这样做更简单 & 更直接。

  在实现适配器功能的时候,可以调用自己开发的功能,从而自然地扩展系统的功能。

  将目标类和适配者类解耦,通过引入一个适配器类重用现有的适配者类,而无需修改原有代码。

  同一个适配器可以把适配者类和它的子类都适配到目标接口;可以为不同的目标接口实现不同的适配器,而不需要修改待适配类。

(2)缺点

  过多的使用适配器,会让系统非常零乱,不易整体进行把握。

3.2 类的适配器模式

(1)优点

  仅仅引入一个对象,并不需要额外的字段来引用Adaptee实例。

(2)缺点

  使用对象继承的方式,是静态的定义方式。

3.3 对象的适配器模式

(1)优点

  采用 “对象组合”的方式,是动态组合方式。

(2)缺点

  需要引入对象实例。

特别是需要重新定义Adaptee行为时需要重新定义Adaptee的子类,并将适配器组合适配。

4.应用场景

4.1 适配器的使用场景

4.2 类和对象适配器模式的使用场景

(1)灵活使用时:选择对象的适配器模式

  类适配器使用对象继承的方式,是静态的定义方式;而对象适配器使用对象组合的方式,是动态组合的方式。

(2)需要同时配源类和其子类:选择对象的适配器。

(3)需要重新定义Adaptee的部分行为:选择类适配器

(4)仅仅希望使用方便时:选择类适配器

(5)总结

  建议尽量使用对象的适配器模式,多用合成/聚合、少用继承。

当然,具体问题具体分析,根据需要来选用合适的实现方式。

5.总结

  本文主要对适配器模式进行了全面介绍。

上一篇下一篇

猜你喜欢

热点阅读