java设计模式之适配器模式
适配器模式的定义:
适配器模式又叫作变压器模式,它的功能是将一个类的接口变成客户端所期望的另一个接口,从而使原本因接口不匹配而导致
无法在一起工作的两个类能够一起工作,属于结构型设计模式。
在软件开发过程中,基本上任何问题都可以通过增加一个中间层来解决。适配器模式其实就是一个中间层。适配器模式起着转化
/委托的作用,将一种接口转化为另一种符合需要的接口。
适配器模式的应用场景:
- 已经存在的类,它的方法和需求不匹配(方法结果相同或相似)的情况。
- 适配器模式不是软件设计阶段考虑的设计模式,是随着软件维护,由于不同产品不同厂家造成功能类似而接口不相同情况下的解决方案,有种亡羊补牢的感觉。
适配器模式有三种形式:类适配器、对象适配器、接口适配器。适配器模式一般包含三个角色:
- 目标角色(ITarget):也就是我们期望的接口。
- 源角色(Adaptee):存在于系统中,内容满足客户需求但接口不匹配的接口实例。
- 适配器(Adapter):将Adaptee转化为目标角色ITarget的类实例。
类适配器的UML类图以及通用写法:
类适配器的原理就是通过继承来实现适配器功能。具体做法就是Adapter继承Adaptee并实现ITarget接口,这样Adapter就具备了Adaptee和ITarget的特性,可以将
两者进行转化,其UML类图如下:
我们用一个例子来进行讲解。在中国,民用电都是220V交流电,但用手机使用的锂电池使用的是5V的直流电。因此,当手机充电时,需要使用电源适配器来进行转换,
我们用代码来还原这个场景,首先创建Adaptee角色类,需要被转换的对象AC220,表示220V交流电。
1 2 3 4 5 6 7 | public class AC220 { public int outputAC220V(){ int output = 220 ; System.out.println( "输出电压" + output + "V" ); return output; } } |
创建ITarget角色DC5接口,表示5V直流电。
public interface DC5 { int output5V(); }
创建Adapter角色的电源适配器PowerAdapter类。
public class PowerAdapter extends AC220 implements DC5 { public int output5V() { int adapterInput = super.outputAC220V(); int adapterOutput = adapterInput / 44; System.out.println("使用Adapter输入AC" + adapterInput + "V,输出DC" + adapterOutput + "V"); return adapterOutput; } }
测试代码。
public class Test { public static void main(String[] args) { DC5 adapter = new PowerAdapter(); adapter.output5V(); } }
对象适配器的UML类图及通用写法:
对象适配器的原理就是通过组合来实现适配器的功能。具体做法是,首先让Adapter实现ITarget接口,然后内部持有Adaptee实例。这样做使得代码更加灵活,比如
我们需要将两个不同的源角色(Adaptee)整合成一个ITarget目标角色,显然这个时候用继承就没办法实现了,所以这也是为什么我们要多用组合少用继承的原因。其UML
类图如下:
接前面的示例,代码只需要更改Adapter实现,及去掉继承Adaptee类,并将Adaptee作为内部属性注入,其他与类适配器一致。
public class PowerAdapter implements DC5 { private AC220 ac220; public PowerAdapter(AC220 ac220) { this.ac220 = ac220; } public int output5V() { int adapterInput = ac220.outputAC220V(); int adapterOutput = adapterInput / 44; System.out.println("使用Adapter输入AC" + adapterInput + "V,输出DC" + adapterOutput + "V"); return adapterOutput; } }
接口适配器的UML类图及通用写法:
接口适配器的关注点和前面两个适配器不太一样,当我们的源角色和目标角色的接口能够匹配的情况下,但是我们的目标角色可能包含多个源角色的功能,
也就是有其他的除了源角色对应抽象方法以外的抽象方法,这样如果我们目标角色之间实现源角色接口的话,会多出许多空的实现方法,显得臃肿。此时就需要
使用接口适配器来实现了,接口适配器的UML类图以及写法都和对象适配器的完全一样,唯一的区别是,在目标角色接口中多了几个抽象方法,然后在适配器角
色中多了抽象方法对应的源角色属性注入。所以这里就不再列举了。
适配器模式的优点:
- 能提高类的透明性和复用,但现有的类不需要改变。
- 适配器类和原角色类解耦,提高程序的扩展性。
- 在很多业务场景中符合开闭原则。
适配器模式的缺点:
- 适配器编写过程需要结合业务场景全面考虑,可能会增加系统的复杂性。
- 增加代码阅读难度,降低代码可读性,过多使用适配器会使系统代码变得凌乱。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】博客园携手 AI 驱动开发工具商 Chat2DB 推出联合终身会员
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步