前言
目前在整理总结设计模式,准备将设计模式当一个专题完成,作者写博客的目的只有是为了总结归纳自己的理解,如果有任何问题请帮忙指出,谢谢!
本篇要介绍的就是适配器模式。
需求
目前市面上大多数充电器都是将220V电压进行适配为5V电压供手机使用,但是在日本的电压是110V,为了出口到日本现在需要充电器也要适配110V电压。
这个业务场景用if…else方式很容易实现,就略过了。
适配器模式
1.简介
类适配器模式可采用多重继承方式实现,如 C++ 可定义一个适配器类来同时继承当前系统的业务接口和现有组件库中已经存在的组件接口;Java 不支持多继承,但可以定义一个适配器类来实现当前系统的业务接口,同时又继承现有组件库中已经存在的组件。
简单来说就是,将原本不兼容的接口通过适配修改到统一,方便调用方使用。
2.结构
- 目标(Target)接口:当前系统业务所期待的接口,它可以是抽象类或接口。
- 适配者(Adaptee)类:它是被访问和适配的现存组件库中的组件接口。
- 它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。
2.分类
具体实现方式有:类适配器、对象适配器和接口适配器。
一般的业务场景不太推荐类适配器和对象适配器,以下是用接口适配器实现。
设计模式实现
1.电压实现
/**
* 定义一个抽象的电源
* @author winter
*/
public abstract class Power {
/**
* 默认为220V
* @return
*/
public int output(){
return 220;
}
}
/**
* 220V电压
* @author winter
*/
public class NormalPower extends Power{
@Override
public int output() {
return 220;
}
}
/**
* 110V电压
* @author winter
*/
public class LowPower extends Power {
@Override
public int output() {
return 110;
}
}
2.目标角色
定义一个将电压转成目标电压的接口
/**
* 目标接口 定义一个转换为5V电压的方法
* @author winter
*/
public interface Target {
int change();
}
3.适配器角色
适配110V和220V电压转换功能
/**
* 适配器
* @author winter
*/
public class PowerAdapter implements Target {
private Power power;
public PowerAdapter(Power power) {
this.power = power;
}
@Override
public int change() {
if (power instanceof NormalPower) {
System.out.println("处理220V的电压转换业务...");
return power.output()/44;
}else {
System.out.println("处理110V的电压转换业务...");
return power.output()/22;
}
}
}
4.测试
public static void main(String[] args) {
Target target = new PowerAdapter(new NormalPower());
int dc = target.change();
System.out.println("转换后的电压为:" + dc + " 伏...");
}
处理220V的电压转换业务…
转换后的电压为:5 伏…
总结
1.模式优缺点
优点:
- 客户端通过适配器可以透明地调用目标接口。
- 复用了现存的类,程序员不需要修改原有代码而重用现有的适配者类。
- 将目标类和适配者类解耦,解决了目标类和适配者类接口不一致的问题。
- 符合开闭原则。
缺点:
- 适配器编写过程需要结合业务场景全面考虑,可能会增加系统的复杂性。
- 增加代码阅读难度,降低代码可读性,过多使用适配器会使系统代码变得凌乱。
2.业务场景
- 版本兼容:如老接口改造,不影响旧版本项目使用。
- 输出接口统一,但是输入类型却不可预知。
3.其他
其实适配器模式和策略模式处理的业务非常相似,之前在实际项目中遇到了类似的业务,作者基本上都是用策略模式来设计的,通过这篇简单归纳对适配器模式有了更深了解,牢记设计模式学习的是设计思想而不是实现方式。