• 结构型设计模式之适配器模式


    适配器模式

    适配器模式(Adapter Pattern)又叫做变压器模式,属于结构型设计模式。

    它的功能是将一个类的接口变成客户端所期望的另一种接口,从而使原本因接口不匹配而导致无法在一起工作的两个类能够一起工作。

    适配器就像一个中间层,起着转化委托的作用,将一种接口转化为另一种符合需求的接口。

    在这里插入图片描述

    分类

    适配器模式有3种形式:类适配器、对象适配器、接口适配器

    类适配器:

    类适配器的原理就是通过继承来实现适配器功能。

    对象适配器:

    对象适配器的原理就是通过组合来实现适配器功能。

    接口适配器:

    接口适配器的主要原理就是原理利用抽象类实现接口,并且空实现接口众多方法。

    应用场景

    1.已经存在的类,它的方法和需求不匹配(方法结果相同或相以)的情况。
    
    2.适配器模式不是软件设计阶段考虑的设计模式,是随着软件维护,由于不同产品、不同厂家造成功能类似以而接口不相同情况下的解决方案。
    
    • 1
    • 2
    • 3

    说明:

    当系统存在两种接口A和B,客户端只支持访问A接口,但是当前系统没有A接口对象,但是有B接口对象,但客户无法识别B接口,因此需要通过一个适配器C,将B接口内容转换成A接口,从而使得客户能够从A接口获取得到B接口内容。

    举例:在不同的国家电源电压不一致,但是笔记本充电器通常有一个电压范围,其相当于使用了适配器,让其适应了不通过国家的电压。

    优缺点

    优点:

    1.能提高类的透明性和复用,现有的类复用但不需要改变。
    
    2.目标类和适配器类解耦,提高程序的扩展性。
    
    3.在很多业务场景中符合开闭原则。
    
    • 1
    • 2
    • 3
    • 4
    • 5

    缺点:

    1.适配器编写过程需要全面考虑,可能会增加系统的复杂性。
    
    2.增加代码阅读难度,降低代码可读性,过多使用适配器会使系统代码变得凌乱。
    
    • 1
    • 2
    • 3

    主要角色

    1.目标角色(Target)

    目标角色也就是期望的接口

    2.源角色(Adaptee)

    存在于系统中,内容满足客户需求(需转换),但接口不匹配的接口实例

    3.适配器(Adapter)

    将源角色(Adaptee)转化为目标角色(Target)的类实例

    适配器模式各角色之间的关系

    需要的是Target接口,但Target接口设有一个实例符合需求,而Adaptee实例符合需求;但是无法直接使用Adaptee(接口不兼容);因此需要一个适配器(Adapter)来进行中转,让Adaptee能转化为Target接口形式;

    类适配器

    类适配器的原理就是通过继承来实现适配器功能。

    让Adapter实现Target接口,并且继承Adaptee,这样Adapter就具备Target和Adaptee的特性,就可以将两者进行转化。

    举例:以不同设备使用不同交流电为例,通过电源适配器进行转换说明。

    创建目标角色(Target)

    public interface Target {
        int out();
    }
    
    • 1
    • 2
    • 3

    创建源角色(Adaptee)

    public class Adaptee{
        public int input() {
            System.out.println("输入交流电: 220V");
            return 220;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    创建适配器(Adapter)

    public class Adapter extends Adaptee implements Target {
        @Override
        public int out() {
            int input220V = super.input();
            int output = input220V / 2;
            System.out.println("输出交流电: " + output + "V");
            return output;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    客户端调用

        public static void main(String[] args) {
            Target adapter = new Adapter();
            int result = adapter.out();
            System.out.println(result);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    输入交流电: 220V
    输出交流电: 110V
    110
    
    • 1
    • 2
    • 3

    对象适配器

    对象适配器的原理就是通过组合来实现适配器功能。

    让Adapter实现Target接口,然后内部持有Adaptee实例,然后再Target接口规定的方法内转换Adaptee。

    创建目标角色(Target)

    public interface Target {
        int out();
    }
    
    • 1
    • 2
    • 3

    创建源角色(Adaptee)

    public class Adaptee{
        public int input() {
            System.out.println("输入交流电: 220V");
            return 220;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    创建适配器(Adapter)

    public class Adapter implements Target {
        private Adaptee adaptee;
    
        public Adapter(Adaptee adaptee) {
            this.adaptee = adaptee;
        }
    
        @Override
        public int out() {
            int output = adaptee.input() / 2;
            System.out.println("输出交流电: " + output + "V");
            return output;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    客户端调用

        public static void main(String[] args) {
            Target adapter = new Adapter(new Adaptee());
            int result = adapter.out();
            System.out.println(result);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    输入交流电: 220V
    输出交流电: 110V
    110
    
    • 1
    • 2
    • 3

    接口适配器

    接口适配器的关注点与类适配器和对象适配器的关注点不太一样,类适配器和对象适配器着重于将系统存在的一个角色(Adaptee)转化成目标接口(Target)所需内容,而接口适配器的使用场景是解决接口方法过多,如果直接实现接口,那么类会多出许多空实现的方法,类显得很臃肿。此时,使用接口适配器就能让我们只实现我们需要的接口方法,目标更清晰。

    接口适配器的主要原理就是原理利用抽象类实现接口,并且空实现接口众多方法。

    创建目标角色(Target)

    public interface Target {
        int out1();
        int out2();
        int out3();
        int out4();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    创建源角色(Adaptee)

    public class Adaptee{
        public int input() {
            System.out.println("输入交流电: 220V");
            return 220;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    创建适配器(Adapter)

    public class Adapter implements Target {
    
        protected Adaptee adaptee;
        public Adapter(Adaptee adaptee){
            this.adaptee = adaptee;
        }
    
        @Override
        public int out1() {
            int input220V = adaptee.input();
            int output = input220V / 1;
            System.out.println("输出交流电: " + output + "V");
            return output;
        }
    
        @Override
        public int out2() {
            int input220V = adaptee.input();
            int output = input220V / 2;
            System.out.println("输出交流电: " + output + "V");
            return output;
        }
    
        @Override
        public int out3() {
            return 0;
        }
    
        @Override
        public int out4() {
            return 0;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    客户端调用

        public static void main(String[] args) {
            Target adapter = new Adapter(new Adaptee());
            adapter.out1();
            System.out.println("---------------------");
            
            adapter.out2();
            System.out.println("---------------------");
            
            Target adapter2 = new Adapter(new Adaptee()) {
                @Override
                public int out3() {
                    int input220V = adaptee.input();
                    int output = input220V / 3;
                    System.out.println("输出交流电: " + output + "V");
                    return output;
                }
            };
            adapter2.out3();
            System.out.println("---------------------");
    
            Target adapter3 = new Adapter(new Adaptee()) {
                @Override
                public int out4() {
                    int input220V = adaptee.input();
                    int output = input220V / 4;
                    System.out.println("输出交流电: " + output + "V");
                    return output;
                }
            };
            adapter3.out4();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    输入交流电: 220V
    输出交流电: 220V
    ---------------------
    输入交流电: 220V
    输出交流电: 110V
    ---------------------
    输入交流电: 220V
    输出交流电: 73V
    ---------------------
    输入交流电: 220V
    输出交流电: 55V
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
  • 相关阅读:
    sql中如何添加数据
    AxureRP9的新特性介绍和技巧分享
    快充插线板怎么选?我的办公搭子是它!
    知识管理系统如何提升企业核心竞争力
    【工程光学】平面与平面系统
    ZigBee 3.0实战教程-Silicon Labs EFR32+EmberZnet-3-02:不同BootLoader之间的区别/如何选择
    git stash命令的用法
    释放数据的潜力:用梯度上升法解锁主成分分析(PCA)的神奇
    Cmake输出git内容方式
    2023高教社杯数学建模国赛A题思路解析+代码+论文
  • 原文地址:https://blog.csdn.net/qq_38628046/article/details/126187365