赞
踩
将一个类的接口转换为客户端希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的类一起工作。
比如: 测试类必须使用A类,现在测试类需要在A类的基础上使用B类的一些功能,这时就出现了接口不兼容的问题,此时就可以使用适配器类,将B类与A类整合,适配器类具有了B类的功能,但是可以在定义时,声明为A类(具体通过继承父类或者实现接口的方式),对外表现为A接口,这样测试类就不需要修改使用和定义A类的代码。
具体参照之后的代码案例进行理解。
适配器模式分为类适配器模式和对象适配器模式。类适配器模式采用了继承的方式实现适配器类,而对象适配器模式采用了组合或者聚合的方式实现适配器类。
前者类之间的耦合度比后者高,且要求使用者理解现有组件库的相关组件的内部结构,所以应用相对较少些。
另外还有一种适配器模式:接口适配器模式,当不希望实现一个接口中所有的方法时,可以创
建一个抽象类Adapter
,实现所有方法。而此时我们只需要继承该抽象类即可。
适配器模式主要包含一下主要角色:
实现方式:定义一个适配器类来实现当前系统的业务接口,同时又继承现有组件库中已经存在的组件。
举一个简单的例子:假设我们有一个手机需要充电,他的充电器的充电头为PlugA,但是因为一些问题(自行脑补),电源需要经过充电头PlugB转换之后,才能给PlugA使用为手机充电。此时,就需要将PlugA与电源通过PlugB进行适配。可以通过适配器模式来模拟该场景,电源可以理解为测试类的充电操作。
可以参考代码理解。
类适配器模式是通过继承的方式实现的,实现的类图如下:
其中:
PlugA
与PlugB
为两个插头的接口,PlugAImpl
与PlugBImpl
为其实现类。MobilePhone
类为手机类,其中有一个充电的方法,其输入只接受PlugA
类型的数据,代表了其只能通过PlugA
充电。PlugAAdapterPlugB
类为适配器类,其继承了PlugBImpl
,实现了PlugA
接口。所以其具有的PlugBImpl
的功能,并且其顶层类型可为PlugA
,可供MobilePhone
调用。PlugAAdapterPlugB
创建插头对象PlugA
,该对象在内部已经经过PlugB
的转换。1.PlugA
与PlugB
接口:
public interface PlugA {
/*
适配者类的接口
*/
// 实现方法插头A充电
void ChargeFromPlugA();
}
public interface PlugB {
/*
目标接口
*/
// 充电
void ChargeFromPlugB();
}
2.接口的实现类
public class PlugAImpl implements PlugA{
@Override
public void ChargeFromPlugA() {
System.out.println("用插头A充电");
}
}
public class PlugBImpl implements PlugB{
@Override
public void ChargeFromPlugB() {
System.out.println("用插头B转换");
}
}
3.手机类
public class MobilePhone {
//手机类
//使用A接口充电
public void ChargeFromPlugA(PlugA plugA){
if(plugA == null){
throw new NullPointerException("plug is not null!");
}
plugA.ChargeFromPlugA();
}
}
4.适配器类
public class PlugAAdapterPlugB extends PlugBImpl implements PlugA{
@Override
public void ChargeFromPlugA() {
ChargeFromPlugB();
System.out.println("使用插头A充电");
}
}
5.测试类
public class test {
public static void main(String[] args) {
System.out.println("===1.手机不使用转接头充电===");
MobilePhone mobilePhone = new MobilePhone();
mobilePhone.ChargeFromPlugA(new PlugAImpl());
System.out.println("===2.手机使用转接头B转到A充电[类适配器模式]===");
PlugA plugA = new PlugAAdapterPlugB();
mobilePhone.ChargeFromPlugA(plugA);
}
}
结果:
PlugAImpl
类有接口规范的时候可以使用,当没有的时候就无法这样实现了。对象适配器模式采用组合或者聚合的方式实现适配器类,也就是说我们再需要PlugBImp
l类时,可以通过聚合的方式,在适配器类内部创建PlugB
类型的成员变量(当然创建PlugBImpl
类型的变量也可以),然后通过构造方法将PlugB
传入适配器类,适配器调用其方法,这样适配器就没有继承作用上的父类了。
如果客户端类即PlugAImpl
在实现的时候,没有接口规范,那我们就可以直接采用对PlugAImpl
继承的方式来实现适配器类,这样就避免了类适配器模式中因为继承了PlugBImpl
,而PlugAImpl
类没有接口规范而造成的无法实现适配器的问题。
该种模式下的类图如下所示,就不再过多解释,其中处理图中的实现关系外,适配器类PlugAAdapterPlugB_instance
与PlugB
是聚合关系,MobilePhone
与PlugA
为依赖关系。
代码如下:
其他代码不变,只修改适配器类和测试类即可。
适配器类:
public class PlugAAdapterPlugB_instance implements PlugA{
private PlugB plugB;
public PlugAAdapterPlugB_instance(PlugB plugB) {
this.plugB = plugB;
}
@Override
public void ChargeFromPlugA() {
plugB.ChargeFromPlugB();
System.out.println("使用插头A充电");
}
}
测试类:
public class test {
public static void main(String[] args) {
System.out.println("===1.手机不使用转接头充电===");
MobilePhone mobilePhone = new MobilePhone();
mobilePhone.ChargeFromPlugA(new PlugAImpl());
System.out.println("===2.手机使用转接头B转到A充电[类适配器模式]===");
PlugA plugA = new PlugAAdapterPlugB();
mobilePhone.ChargeFromPlugA(plugA);
System.out.println("===3.手机使用转接头B转到A充电[对象适配器模式]===");
PlugA plugA2 = new PlugAAdapterPlugB_instance(new PlugBImpl());
mobilePhone.ChargeFromPlugA(plugA);
}
}
结果:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。