【设计模式】Java设计模式 - 适配器模式

简介: 适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。就像电脑/投影仪那种,电脑要通过接线的方式投影,但是在以前的接口都是VGA接口,然而我们的电脑却大多都是HDMI类型的,这就需要转接头来转换接口,于是,这个转接头就充当着适配器的身份。

Java设计模式 - 适配器模式

😄 生命不息,写作不止
🔥 继续踏上学习之路,学之分享笔记
👊 总有一天我也能像各位大佬一样
🏆 一个有梦有戏的人 @怒放吧德德
🌝分享学习心得,欢迎指正,大家一起学习成长!

今天的内容有点多,也要努力学完!

java设计模式2.jpg

简介

适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。就像电脑/投影仪那种,电脑要通过接线的方式投影,但是在以前的接口都是VGA接口,然而我们的电脑却大多都是HDMI类型的,这就需要转接头来转换接口,于是,这个转接头就充当着适配器的身份。
适配器模式分为:类适配器模式、对象适配器模式、接口适配器模式
image.png

1、类适配器模式

本次实验使用手机充电的电压转换为例,其实就是这样的,通过适配器去继承被适配者,并且实现目标接口。
整体如下:
image.png

①、被适配者

手机不能直接使用工作电压充电,因此需要把工作电压降压到能提供手机充电的电压,这里先准备好一个工作电压类,输出220V标准工作电压。

package com.lyd.demo.classadapter;
/**
 * @Author: lyd
 * @Description: 类适配器 - 工作电压:220V
 * @Date: 2022-08-27
 */
public class WorkingVoltage {
    public int outputWorkingPower() {
        int otp = 220; // 工作电压输出220V
        System.out.println("工作电压输出[" + otp + "]V");
        return otp;
    }
}

②、充电电压接口

提供一个获取充电电压的接口,提供给适配器实现。

package com.lyd.demo.classadapter;
/**
 * @Author: lyd
 * @Description: 类适配器 - 充电器的电压
 * @Date: 2022-08-27
 */
public interface IChargingVoltage {
    public int outputChangingPower();
}

③、适配器

在实现充电电压类的方法中进行电压转换。

package com.lyd.demo.classadapter.adapter;
import com.lyd.demo.classadapter.IChargingVoltage;
import com.lyd.demo.classadapter.WorkingVoltage;
/**
 * @Author: lyd
 * @Description: 充电适配器
 * @Date: 2022-08-27
 */
public class ChargingAdapter extends WorkingVoltage implements IChargingVoltage {
    public int outputChangingPower() {
        int workPower = outputWorkingPower(); // 获得工作电压
        int changingPower = workPower / 44; // 充电电压
        System.out.println("经过适配器降压到[" + changingPower + "]V");
        return changingPower;
    }
}

④、实例

通过适配器实现的接口方法去获得到修改的数据,原理很简单,就是可以理解为继承第一个类获取其属性数据,在通过实现接口方法去修改。在类适配器,能达到期望结果,java是单继承,就是他需要去继承类,这是他的缺点。
测试类

package com.lyd.demo.classadapter.test;
import com.lyd.demo.classadapter.IChargingVoltage;
import com.lyd.demo.classadapter.adapter.ChargingAdapter;
/**
 * @Author: lyd
 * @Description: 测试类适配器
 * @Date: 2022-08-27
 */
public class ClassAdapterTest {
    public static void main(String[] args) {IChargingVoltage chargingVoltage = new ChargingAdapter();
        System.out.println("转换后的电压:" + chargingVoltage.outputChangingPower());
    }
}

运行结果
image.png

2、对象适配器模式

由于类适配器需要继承,并不是很好,因此,可以使用不继承的方式,就是需要在适配器中获取被适配者的对象。根据合成复用原则,使用组合代替继承。

①、适配器类

其他类无需改动,只要将适配器类的继承方式改成不继承的方式。

采用构造器初始化对象来获得对象。
package com.lyd.demo.objectadapter.adapter;
import com.lyd.demo.classadapter.IChargingVoltage;
import com.lyd.demo.classadapter.WorkingVoltage;
/**
 * @Author: lyd
 * @Description: 充电适配器
 * @Date: 2022-08-27
 */
public class ChargingAdapter implements IChargingVoltage {
    private WorkingVoltage workingVoltage;
    public ChargingAdapter(WorkingVoltage workingVoltage) {
        this.workingVoltage = workingVoltage;
    }
    public int outputChangingPower() {
        if (workingVoltage != null) {
            int workPower = workingVoltage.outputWorkingPower();
            // 获得工作电压
            int changingPower = workPower / 44; // 充电电压
            System.out.println("经过适配器降压到[" + changingPower + "]V");
            return changingPower;
        }
        return 0;
    }
}

②、实例

测试的时候只需要将new实例化对象带进去即可

public static void main(String[] args) {
    ChargingAdapter chargingAdapter = new ChargingAdapter(new WorkingVoltage());
    System.out.println("转换后的电压:" + chargingAdapter.outputChangingPower());
}

运行结果
image.png

对象适配模式与类适配模式基本上是一样的,就只是将类适配模式的继承方式改编成通过构造方法去获取对象,使得以更加灵活。

3、接口适配器

不需要实现所有方法,只想实现其中某个方法,可以设计一个抽象接口,并且让他实现所有接口的空方法,即不需要写方法体。

①、例1

例如:
定义一个接口里面包含几个未实现的方法

package com.lyd.demo.interfaceadapter;
/**
 * @Author: lyd
 * @Description: 接口
 * @Date: 2022-08-27
 */
public interface Interfaces {
    public void show1();
    public void show2();
    public void show3();
    public void show4();
}

定义抽象接口,并且实现空方法

package com.lyd.demo.interfaceadapter;
/**
 * @Author: lyd
 * @Description: 适配器,默认实现空方法,这样调用适配器的时候就可以根据自己想要的方法去重写了
 * @Date: 2022-08-27
 */
public abstract class InterfacesAdapter implements Interfaces {
    public void show1() {
        System.out.println("abs show 1");
    }
    public void show2() {
        System.out.println("abs show 2");
    }
    public void show3() {
        System.out.println("abs show 3");
    }
    public void show4() {
        System.out.println("abs show 4");
    }
}

使用的时候根据自己需要去实现
通过实例化适配器,在其中去重写方法,调用的时候会使用重写的方法,如果没有重写就是调用父类的方法。

package com.lyd.demo.interfaceadapter;
/**
 * @Author: lyd
 * @Description: 接口适配器测试
 * @Date: 2022-08-27
 */
public class Main {
    public static void main(String[] args) {
        InterfacesAdapter adapter = new InterfacesAdapter() {
            @Override
            public void show1() { // 只重写一个方法
                System.out.println("adapter show 1");
            }
        };
        adapter.show1();
        adapter.show3(); // 调用的时候就是抽象类的空方法
    }
}

运行结果
image.png

②、例2

本例详情可以看菜鸟教程 https://www.runoob.com/design-pattern/adapter-pattern.html 我用了和他不同的例子,但是结构都是一样的。
再来一个例子,加入说我需要处理图片,但是图片的格式不同,针对不同格式需要不同的方法来处理。
定义接口和特殊格式处理接口

package com.lyd.demo.runoob;
/**
 * @Author: lyd
 * @Description: <p>https://www.runoob.com/design-pattern/adapter-pattern.html</p>
 * @Date: 2022-08-27
 */
public interface PictureOperate {
    public void operate(String pictureType, String fileName);
}
package com.lyd.demo.runoob;
/**
 * @Author: lyd
 * @Description: 高级图片处理
 * @Date: 2022-08-27
 */
public interface AdvancedPictureOperate {
    public void operateAi(String fileName);
    public void operateSvg(String fileName);
}

定义处理特殊图片的类,分别实现各自需要的方法,不需要的放为空方法

package com.lyd.demo.runoob;

/**
 * @Author: lyd
 * @Description: .Ai图片的操作
 * @Date: 2022-08-27
 */
public class AiOperate implements AdvancedPictureOperate{

    @Override
    public void operateAi(String fileName) {
        System.out.println("操作 " + fileName + " 的ai图片");
    }

    @Override
    public void operateSvg(String fileName) {
        // todo
    }
}
package com.lyd.demo.runoob;
/**
 * @Author: lyd
 * @Description: .svg图片的操作
 * @Date: 2022-08-27
 */
public class SvgOperate implements AdvancedPictureOperate {
    @Override
    public void operateAi(String fileName) {
        // todo
    }
    @Override
    public void operateSvg(String fileName) {
        System.out.println("操作 " + fileName + " 的svg图片");
    }
}

图片适配器
根据不同的类型来声明不同类以及使用对应方法

package com.lyd.demo.runoob;

/**
 * @Author: lyd
 * @Description: 适配器
 * @Date: 2022-08-27
 */
public class PictureAdapter implements PictureOperate{
    AdvancedPictureOperate advancedPictureOperate;

    public PictureAdapter(String pictureType) {
        if (pictureType.equalsIgnoreCase("ai")) {
            advancedPictureOperate = new AiOperate();
        } else if (pictureType.equalsIgnoreCase("svg")) {
            advancedPictureOperate = new SvgOperate();
        }
    }

    @Override
    public void operate(String pictureType, String fileName) {
        if (pictureType.equalsIgnoreCase("ai")) {
            advancedPictureOperate.operateAi(fileName);
        } else if (pictureType.equalsIgnoreCase("svg")) {
            advancedPictureOperate.operateSvg(fileName);
        }
    }
}

操作类

package com.lyd.demo.runoob;
/**
 * @Author: lyd
 * @Description:
 * @Date: 2022-08-27
 */
public class PhotoOperate implements PictureOperate{
    PictureAdapter pictureAdapter;
    @Override
    public void operate(String pictureType, String fileName) {
        if (pictureType.equalsIgnoreCase("ai") || pictureType.equalsIgnoreCase("svg")) {
            pictureAdapter = new PictureAdapter(pictureType);
            pictureAdapter.operate(pictureType, fileName);
        } else if (pictureType.equalsIgnoreCase("jpg")) { // 非特殊格式
            System.out.println("不用特殊方法处理:" + fileName);
        } else {
            System.out.println("格式错误");
        }
    }
}

测试

package com.lyd.demo.runoob;
/**
 * @Author: lyd
 * @Description:
 * @Date: 2022-08-27
 */
public class test {
    public static void main(String[] args) {
        PhotoOperate photoOperate = new PhotoOperate();
        photoOperate.operate("jpg", "a.jpg");
        photoOperate.operate("svg", "b.svg");
        photoOperate.operate("ai", "c.ai");
        photoOperate.operate("vip", "d.vip");
    }
}

运行结果
image.png

👍创作不易,如有错误请指正,感谢观看!记得一键三连哦!👍

💓德德小建议:

理解设计模式不是一件简单的事情,需要不断的学习和动手去练习,才能理解。只有掌握好设计模式,才能够真正的理解SpringAOP和Mybatis的底层原理。各位读者可以和我一样,动手敲一敲代码,甚至用不同的例子来做,通过debug一步一步调试,还有就是多看看别人的例子。能够有助于理解!谢谢各位观看指点!❤️ ❤️ ❤️
相关文章
|
26天前
|
设计模式 JSON 前端开发
前端必须掌握的设计模式——适配器模式
适配器模式是一种结构型设计模式,用于使接口不兼容的对象能够相互合作。通过在客户端和系统之间引入一个“中间层”适配器,将不同类型的输入数据转换为系统能处理的标准格式,减轻系统的负担,提高扩展性和可维护性。例如,MacBook的扩展坞将多种接口(如HDMI、USB)转换为Type-C接口,实现多接口兼容。
|
2月前
|
设计模式 消息中间件 搜索推荐
Java 设计模式——观察者模式:从优衣库不使用新疆棉事件看系统的动态响应
【11月更文挑战第17天】观察者模式是一种行为设计模式,定义了一对多的依赖关系,使多个观察者对象能直接监听并响应某一主题对象的状态变化。本文介绍了观察者模式的基本概念、商业系统中的应用实例,如优衣库事件中各相关方的动态响应,以及模式的优势和实际系统设计中的应用建议,包括事件驱动架构和消息队列的使用。
|
2月前
|
设计模式 Java 数据库连接
Java编程中的设计模式:单例模式的深度剖析
【10月更文挑战第41天】本文深入探讨了Java中广泛使用的单例设计模式,旨在通过简明扼要的语言和实际示例,帮助读者理解其核心原理和应用。文章将介绍单例模式的重要性、实现方式以及在实际应用中如何优雅地处理多线程问题。
46 4
|
3月前
|
设计模式 Java 程序员
[Java]23种设计模式
本文介绍了设计模式的概念及其七大原则,强调了设计模式在提高代码重用性、可读性、可扩展性和可靠性方面的作用。文章还简要概述了23种设计模式,并提供了进一步学习的资源链接。
64 0
[Java]23种设计模式
|
2月前
|
设计模式 JavaScript Java
Java设计模式:建造者模式详解
建造者模式是一种创建型设计模式,通过将复杂对象的构建过程与表示分离,使得相同的构建过程可以创建不同的表示。本文详细介绍了建造者模式的原理、背景、应用场景及实际Demo,帮助读者更好地理解和应用这一模式。
|
3月前
|
设计模式 监控 算法
Java设计模式梳理:行为型模式(策略,观察者等)
本文详细介绍了Java设计模式中的行为型模式,包括策略模式、观察者模式、责任链模式、模板方法模式和状态模式。通过具体示例代码,深入浅出地讲解了每种模式的应用场景与实现方式。例如,策略模式通过定义一系列算法让客户端在运行时选择所需算法;观察者模式则让多个观察者对象同时监听某一个主题对象,实现松耦合的消息传递机制。此外,还探讨了这些模式与实际开发中的联系,帮助读者更好地理解和应用设计模式,提升代码质量。
Java设计模式梳理:行为型模式(策略,观察者等)
|
3月前
|
设计模式 Java
Java设计模式
Java设计模式
45 0
|
3月前
|
设计模式 Java
Java设计模式之外观模式
这篇文章详细解释了Java设计模式之外观模式的原理及其应用场景,并通过具体代码示例展示了如何通过外观模式简化子系统的使用。
38 0
|
14天前
|
设计模式 前端开发 搜索推荐
前端必须掌握的设计模式——模板模式
模板模式(Template Pattern)是一种行为型设计模式,父类定义固定流程和步骤顺序,子类通过继承并重写特定方法实现具体步骤。适用于具有固定结构或流程的场景,如组装汽车、包装礼物等。举例来说,公司年会节目征集时,蜘蛛侠定义了歌曲的四个步骤:前奏、主歌、副歌、结尾。金刚狼和绿巨人根据此模板设计各自的表演内容。通过抽象类定义通用逻辑,子类实现个性化行为,从而减少重复代码。模板模式还支持钩子方法,允许跳过某些步骤,增加灵活性。
|
2月前
|
设计模式 安全 Java
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式