适配器模式
1.适配器模式是什么
1.百度百科
在计算机编程中,适配器模式(有时候也称包装样式或者包装)将一个类的接口适配成用户所期待的。一个适配允许通常因为接口不兼容而不能在一起工作的类工作在一起,做法是将类自己的接口包裹在一个已存在的类中。
2.维基百科
In software engineering, the adapter pattern is a software design pattern (also known as Wrapper, an alternative naming shared with the Decorator pattern) that allows the interface of an existing class to be used as another interface.[1] It is often used to make existing classes work with others without modifying their source code.
3.lz理解
将一个类或者对象转换成客户端希望的另外一个类或者对象,让两个不匹配的类或者对象能协同工作。主要解决兼容性的问题。比如三头插头转换为两头插头。type-c转换为use等都是适配器模式的体现。
4.核心角色
目标(Target)角色:这就是所期待得到的接口。注意:由于这里讨论的是类适配器模式,因此目标不可以是类。
源(Adapee)角色:现在需要适配的接口。
适配器(Adaper)角色:适配器类是本模式的核心。适配器把源接口转换成目标接口。显然,这一角色不可以是接口,而必须是具体类。
2.适配器模式解决了什么问题
解决了目标角色与源角色不匹配无法同时工作的问题。
解除耦合: 通过引入一个适配器重用现有的源,而无需修改原有代码。
更好的复用性:系统需要使用源,而此类的接口不符合系统的需要。那么通过适配器模式就可以让这些功能得到更好的复用。
更好的扩展性:在实现适配器功能的时候,可以调用自己开发的功能,从而自然地扩展系统的功能。也可以将多个源角色适配到同一个目标角色中。
调用统一: 客户端可以调用同一接口,因而对客户端来说是透明的。这样做更简单、更直接、更紧凑。
3.适配器模式用法
适配器大致分为三类:类的适配器模式、接口适配模式、对象适配器模式
1.类的适配器模式
类的适配是为了更改实现方式,就拿typec转换usb来说
//typec接口
public interface TypeC {
void TypeCData();
}
//源角色 usb接口
public interface Usb {
void usbData();
}
//目标角色: 电脑上具体的typec接口
public class FastTypeC implements TypeC {
@Override
public void TypeCData() {
System.out.println("FasttypeC被调用了");
}
}
/**
* 适配器角色: usb转换为typeC
*/
public class UsbToTypeCAdapter extends FastTypeC implements Usb{
//将typec转换为usb
@Override
public void usbData() {
TypeCData();
}
}
客户端调用
public class Customer {
public static void main(String[] args) {
Usb usb = new UsbToTypeCAdapter();
usb.usbData();
}
}
客户端调用的是use接口但是实际上出现的是typec接口实现
FasttypeC被调用了
2.接口适配器模式
需要两相插座、和三相插座的接口
/**
* 两相插座
*/
public interface TwoPhaseSocket {
void neutralWire();
void liveWire();
}
public interface ThreePhaseSocket {
void neutralWire();
void liveWire();
void earthWire();
}
添加适配器
public abstract class SocketAdapter implements ThreePhaseSocket,TwoPhaseSocket{
@Override
public void earthWire() {
//这里不写实现
}
}
适配器具体实现
public class ThreeTransferTwoPhaseSocket extends SocketAdapter{
@Override
public void neutralWire() {
System.out.println("接通了零线");
}
@Override
public void liveWire() {
System.out.println("接通了火线");
}
}
public class Customer {
public static void main(String[] args) {
ThreePhaseSocket tps = new ThreeTransferTwoPhaseSocket();
tps.liveWire();
tps.neutralWire();
tps.earthWire();
}
}
接通了火线
接通了零线
(地线空置)
这种适配器就缩小了接口的大小。
3.对象适配器模式
还是以usb和typeC举例
typec和usb接口与typeC的实现FastTypeC就不在赘述,下面我们看下适配器和调用方式
/**
* usb转换为typeC
*/
public class UsbToTypeCAdapter implements Usb{
private TypeC typeC;
public UsbToTypeCAdapter(TypeC typeC) {
this.typeC = typeC;
}
//将typec转换为usb
@Override
public void usbData() {
typeC.TypeCData();
}
}
public class Customer {
public static void main(String[] args) {
TypeC fastTypeC = new FastTypeC();
Usb usb = new UsbToTypeCAdapter(fastTypeC);
usb.usbData();
}
}
对象适配器是用组合的方式解决适配的问题。
还是那句话用组合解决问题还是用继承解决问题取决于是否需要向上造型,
4.适配器模式的问题
适配过程复杂: 对于对象适配器来说,更换适配器的实现过程比较复杂。
调用混乱:过多的使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是A接口,其实内部被适配成了B接口的实现,一个系统如果太多出现这种情况,无异于一场灾难.
5.适配器模式总结
使用场景:
1.想要使用一个已经存在的类,但是这个类不符合接口规范,导致无法直接访问,这是就需要一个适配器去间接访问这个类。
2.有一个类其内部的某些方法可以被重复使用,我们可以创建适配器来将这个类来适配其他没有提供合适接口的类。
3.某接口设计了太多的方法像要使用必须实现所有接口,可以使用抽象类实现接口,并对多余的方法进行置空。在通过继承抽象类重写来实现,
综上所述,适配器模式主要是用于解决接口与实现类不匹配的问题。主要是接口过大,对多余的接口置空。接口过小,补充部分实现。接口不匹配,转换接口实现等方法来匹配不合适的接口。不过这么做只是权宜之计,过多的适配器会造调用混乱并且代码难以理解,所以最好的方式就是重构代码来调整合适的接口。