一. 概述
将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作。
二. 解决的问题
即Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作。
三. 模式中的角色
3.1目标接口(Target):客户所期待的接口。目标可以是具体的或抽象的类,也可以是接口。
3.2需要适配的类(Adaptee):需要适配的类。
3.3适配器(Adapter):通过包装一个需要适配的对象,把原接口转换成目标接口。
代码结构
Target
public interface Target { void adapterMethod(); }
Adaptee
public class Adaptee { public void adapteeMethod() { Syste.out.ptintln("Adaptee method!"); } }
Adapter
对象适配器:
public class Adapter implements Target { //引入被适配者 private Adaptee adaptee; public Adapter(Adaptee adaptee) { this.adaptee = adaptee; } public void adapterMethod() { System.out.println("Adapter method!"); } }
类适配器:
Public class Adapter extends Adapteee implements Target { public void adapterMethod() { System.out.println("Adapter method!"); } }
Client
public class Test { public static void main(String[] args) { Target target = new Adapter(new Adaptee()); target.adapterMethod(); } }
result
Adapter method!
四、例子
PS2接口
/** * PS2接口,圆口 */ public interface PS2Port { public void workWithPS2(); }
usb接口
/** * USB接口,U口 */ public interface USBPort { public void workWithUSB(); }
PS2ToUSB转换器
/** * 对象适配器 * 将PS2接口装换成USB接口 * 所以此类类型是USB接口(implements USBPort) + 成员变量ps2Port */ public class PS2ToUSB implements USBPort { private PS2Port ps2Port; public PS2ToUSB(PS2Port ps2Port) { this.ps2Port = ps2Port; } @Override public void workWithUSB() { System.out.println("转换的关键在这里,本来是"); ps2Port.workWithPS2(); System.out.println("经过你的转换,现在是USB工作中"); } }
场景类
public class Client { public static void main(String[] args) { //1.我现在有一个PS2接口 PS2Port ps2Port = new WorkPiece(); //2.但是我需要的是一个USB接口啊,对我(client)来说,我只认识USB接口 //3.经过PS2ToUSB的转换,PS2接口变成了USB接口 USBPort ps2ToUsbPort = new PS2ToUSB(ps2Port); ps2ToUsbPort.workWithUSB(); } }
其中的WorkPiece 只是一个PS2接口的一个子类
public class WorkPiece implements PS2Port { public void workWithPS2() { System.out.println("PS2工作中"); } }
五. 模式总结
5.1 优点
-
通过适配器,客户端可以调用同一接口,因而对客户端来说是透明的。这样做更简单、更直接、更紧凑。
-
复用了现存的类,解决了现存类和复用环境要求不一致的问题。
-
将目标类和适配者类解耦,通过引入一个适配器类重用现有的适配者类,而无需修改原有代码。
-
一个对象适配器可以把多个不同的适配者类适配到同一个目标,也就是说,同一个适配器可以把适配者类和它的子类都适配到目标接口。
5.2 缺点
对于对象适配器来说,更换适配器的实现过程比较复杂。
5.3 适用场景
-
系统需要使用现有的类,而这些类的接口不符合系统的接口。
-
想要建立一个可以重用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。
-
两个类所做的事情相同或相似,但是具有不同接口的时候。
-
旧的系统开发的类已经实现了一些功能,但是客户端却只能以另外接口的形式访问,但我们不希望手动更改原有类的时候。
-
使用第三方组件,组件接口定义和自己定义的不同,不希望修改自己的接口,但是要使用第三方组件接口的功能。
5.4 “对象”适配器和“类”适配器。
1)对象适配器:使用对象组合,以修改的接口包装被适配者,被适配者的任何子类都可以搭配着适配器使用。
2)类适配器:使用继承,不需要重新实现整个被适配者。
6. 适配器应用举例
手机电源适配器
在java 中有一种叫做“缺省适配模式”的应用,它和我们所讲的适配器模式是完全的两种东西。缺省适配模式是为一个接口提供缺省的实现,这样子类型就可以从缺省适配模式中进行扩展,避免了从原有接口中扩展时要实现一些自己不关心的接口。在java.awt.event 中的XXXAdapter 就是它的很好的例子