【设计模式】Java设计模式 – 适配器模式
? 不断学习才是王道
? 继续踏上学习之路,学之分享笔记
? 总有一天我也能像各位大佬一样
?原创作品,更多关注我CSDN: 一个有梦有戏的人
?准备将博客园、CSDN一起记录分享自己的学习心得!!!
?分享学习心得,欢迎指正,大家一起学习成长!
今天的内容有点多,也要努力学完!
目录
- 【设计模式】Java设计模式 – 适配器模式
- 简介
- 1、类适配器模式
- ①、被适配者
- ②、充电电压接口
- ③、适配器
- ④、实例
- 2、对象适配器模式
- ①、适配器类
- ②、实例
- 3、接口适配器
- ①、例1
- ②、例2
简介
适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。就像电脑/投影仪那种,电脑要通过接线的方式投影,但是在以前的接口都是VGA接口,然而我们的电脑却大多都是HDMI类型的,这就需要转接头来转换接口,于是,这个转接头就充当着适配器的身份。
适配器模式分为:类适配器模式、对象适配器模式、接口适配器模式
1、类适配器模式
本次实验使用手机充电的电压转换为例,其实就是这样的,通过适配器去继承被适配者,并且实现目标接口。
整体如下:
①、被适配者
手机不能直接使用工作电压充电,因此需要把工作电压降压到能提供手机充电的电压,这里先准备好一个工作电压类,输出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()); }}
运行结果
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());}
运行结果
对象适配模式与类适配模式基本上是一样的,就只是将类适配模式的继承方式改编成通过构造方法去获取对象,使得以更加灵活。
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(); // 调用的时候就是抽象类的空方法 }}
运行结果
②、例2
本例详情可以看菜鸟教程 https://www.runoob.com/design-pattern/adapter-pattern.html 我用了和他不同的例子,但是结构都是一样的。
再来一个例子,加入说我需要处理图片,但是图片的格式不同,针对不同格式需要不同的方法来处理。
定义接口和特殊格式处理接口
package com.lyd.demo.runoob;/** * @Author: lyd * @Description: https://www.runoob.com/design-pattern/adapter-pattern.html
* @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"); }}
运行结果
?创作不易,如有错误请指正,感谢观看!记得一键三连哦!?
?德德小建议:
理解设计模式不是一件简单的事情,需要不断的学习和动手去练习,才能理解。只有掌握好设计模式,才能够真正的理解SpringAOP和Mybatis的底层原理。各位读者可以和我一样,动手敲一敲代码,甚至用不同的例子来做,通过debug一步一步调试,还有就是多看看别人的例子。能够有助于理解!谢谢各位观看指点!❤️ ❤️ ❤️