设计模式之适配器模式
概述
适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。
适配器模式将某个类的接口转换成客户端期望的另一个接口表示,主的目的是兼容性,让原本因接口不匹配不能一起工作的两个类可以协同工作。其别名为包装器(Wrapper)
这种模式涉及到一个单一的类,该类负责加入独立或不兼容的接口功能。举个真实的例子,读卡器是作为内存卡和笔记本之间的适配器。您将内存卡插入读卡器,再将读卡器插入笔记本,这样就可以通过笔记本来读取内存卡。
主要分为三类:类适配器模式、对象的适配器模式、接口的适配器模式
适配器的流程类似如下:需要被适配的->Adapter->最终想要的
特点:
1、可以让任何两个没有关联的类一起运行。
2、提高了类的复用。
3、增加了类的透明度。
4、灵活性好。
注意:适配器不是在详细设计时添加的,主要是解决正在服役的项目的问题。
使用场景
- 系统需要使用现有的类,而这些类的接口不符合系统的需要。
- 想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。
- 需要一个统一的输出接口,而输入端的类型不可预知。
在实际使用中无需过于拘泥于以下设计模式的例子,可根据实际业务需要进行设计。
电压类适配器示例
场景:充电器例子,需要将220v的电压转换为5v的电压。
需要被适配已有220v电压的类
/**
* 需要适配已有220v电压的类
*/
static class Voltage220 {
public int output220V(){
System.out.println("输出220v电压");
return 220;
}
}
需要的5v的接口
/**
* 需要的5v的接口
*/
interface Voltage5 {
/**
* 需要输出5v电压
*/
int output5V();
}
电压适配器
/**
* 适配器
*/
static class VoltageAdapter extends Voltage220 implements Voltage5 {
@Override
public int output5V() {
// 将输入5v的参数转为220v的获取执行结果
int voltage = output220V();
// 将结果转换为5v需要的返回结果
System.out.println("适配器开始工作,转换电压为5v");
return voltage/44;
}
}
使用
public static void main(String[] args) {
// 创建Voltage5时使用适配器来创建
Voltage5 voltage5 = new VoltageAdapter();
int voltage = voltage5.output5V();
if (voltage==5){
System.out.println("电压适配成功,开始充电");
}else {
System.out.println("电压适配失败,充电器即将爆炸,请马上断开电源");
}
}
类适配器,让Adapter继承需要被适配的的类,在里面对其进行处理;由于Java的单继承机制,其使用成本也增加了;
对象适配器
/**
* 需要的5v的接口
*/
interface Voltage5 {
/**
* 需要输出5v电压
*/
int output5V();
}
/**
* 需要适配已有220v电压的类
*/
static class Voltage220 {
public int output220V(){
System.out.println("输出220v电压");
return 220;
}
}
static class VoltageAdapter implements Voltage5 {
private Voltage220 voltage220;
// 让适配器持有需要适配的对象
public VoltageAdapter(Voltage220 voltage220){
this.voltage220 = voltage220;
}
@Override
public int output5V() {
int voltage = voltage220.output220V();
System.out.println("适配器开始工作,转换电压为5v");
return voltage/44;
}
}
使用
public static void main(String[] args) {
VoltageAdapter voltageAdapter = new VoltageAdapter(new Voltage220());
int voltage = voltageAdapter.output5V();
if (voltage==5){
System.out.println("电压适配成功,开始充电");
}else {
System.out.println("电压适配失败,充电器即将爆炸,请马上断开电源");
}
}
将对象传递给适配器
接口适配器
interface WxPay {
void pay();
void refund();
}
static abstract class WxPayAdapter implements WxPay {
@Override
public void pay(){
}
@Override
public void refund(){
}
}
使用
public static void main(String[] args) {
WxPay wxPay = new WxPay() {
@Override
public void pay() {
System.out.println("支付实现");
}
@Override
public void refund() {
System.out.println("退款实现");
}
};
wxPay.pay();
// 使用适配器后只需要实现我们需要的即可
WxPayAdapter wxPayAdapter = new WxPayAdapter() {
@Override
public void pay() {
System.out.println("支付实现");
}
};
wxPayAdapter.pay();
}
以接口为目标的适配器;这种方式在安卓中非常常见,比如添加相关的监听器,我只需要实现我们需要的即可,对应不需要的无需去实现,简化了代码。
接口升级兼容示例
未使用设计模式时
public class NoAdapterPattern {
public static void main(String[] args) {
MediaPlayerV1 oldObject = new MediaPlayerV1Impl();
MediaPlayerV2 newObject = new MediaPlayerV2Impl();
oldObject.play();
newObject.play();
}
/**
* v1版本接口
*/
public static interface MediaPlayerV1 {
void play();
}
/**
* v1版本接口实现类
*/
public static class MediaPlayerV1Impl implements MediaPlayerV1 {
@Override
public void play() {
System.out.println("播放mp3");
}
}
/**
* v2版本接口
*/
public static interface MediaPlayerV2 {
void play();
}
/**
* v2版本接口实现类
*
*/
public static class MediaPlayerV2Impl implements MediaPlayerV2 {
@Override
public void play() {
System.out.println("播放mp4");
}
}
}
使用类适配器模式
public class AdapterPatter {
public static void main(String[] args) {
// 将v1版本的转换为v2版本的接口
MediaPlayerV2 oldObject = new NewInterfaceAdapter();
MediaPlayerV2 newObject = new MediaPlayerV2Impl();
oldObject.play();
newObject.play();
}
/**
* 定义一个适配器类
*/
public static class NewInterfaceAdapter implements MediaPlayerV2 {
private final MediaPlayerV1 v1;
public NewInterfaceAdapter(){
this.v1 = new MediaPlayerV1Impl();
}
@Override
public void play() {
// 实际调用v1版本的实现
this.v1.play();
}
}
/**
* v1版本接口
*/
public static interface MediaPlayerV1 {
void play();
}
/**
* v1版本接口实现类
*/
public static class MediaPlayerV1Impl implements MediaPlayerV1 {
@Override
public void play() {
System.out.println("播放mp3");
}
}
/**
* v2版本接口
*/
public static interface MediaPlayerV2 {
void play();
}
/**
* v2版本接口实现类
*/
public static class MediaPlayerV2Impl implements MediaPlayerV2 {
@Override
public void play() {
System.out.println("播放mp4");
}
}
}
适配器的新接口方法的实现,全部基于老接口实现类的老方法来实现即可;对于调用方,只要使用适配器来开发即可,就可以通过面向新接口开发,底层使用老接口实现类。