认识设计模式(七)---适配器模式
项目需求
基本介绍
- 适配器模式把某个类的接口转换成客户端期望的另一个接口表示,让原来因为接口不匹配不能一起工作的两个类可以协同工作
- 适配器模式属于结构型模式
- 主要分为三类:类适配器模式、对象适配器模式、接口适配器模式
原理分析
- 适配器模式:把一个类的接口转换成另一个接口,让原来不兼容的接口变得可以兼容
- 从用户的角度看不到被适配者,是解耦的
- 用户调用适配器转化出来的目标接口方法,适配器再调用适配者的相关接口方法
- 用户收到反馈结果,感觉只是和目标接口交互
- 适配器类通过继承src类,实现dst类接口,完成src->dst的适配
类适配器模式
代码示例
(1)5V充电器接口(目标)
output5V方法:输出为5V
public interface IVoltage5V {
public int output5V();
}
(2)220V充电器类(被适配的类)
output220V方法:输出为220V
public class VoItage220V {
//输出220V的电压
public int output220V(){
int src=220;
System.out.println("电压="+src+"伏");
return src;
}
}
(3)适配器类
- 实现目标接口
- 重写目标接口里的方法,在方法中调用被适配的方法,然后进行处理
public class VoltageAdapter extends VoItage220V implements IVoltage5V {
@Override
public int output5V() {
int srcV=output220V();
int dstV=srcV/44;
return dstV;
}
}
(4)手机类
public class Phone {
public void charging(IVoltage5V iVoltage5V){
if(iVoltage5V.output5V()==5){
System.out.println("电压为5V,可以充电");
}else if(iVoltage5V.output5V()>5){
System.out.println("电压大于5V,不能充电");
}
}
}
(5)测试类
public class Client {
public static void main(String[] args) {
System.out.println("===类适配器模式===");
Phone phone=new Phone();
phone.charging(new VoltageAdapter());
}
}
UML图
类适配器模式注意事项和细节
- java是单继承机制,所以类适配器需要继承src类这一点算是一个缺点,因为这要求dst必须是借楼,有一定的局限性
- src类的方法Adapter中会暴露出来,也增加了使用的成本
- 因为继承了src类,所以它可以根据需求来重写src类的方法,使得Adapter的灵活性增强了
对象适配器模式
基本介绍
- 和类适配器模式相同,知识把Adapter类做修改,不是继承src类,而是持有src类的实例,以解决兼容性的问题。
也就是:持有src类,实现dst接口,完成src->dst的适配 - 根据“合成复用原则”,在系统中尽量使用关联关系(聚合)来替代继承关系
- 对象适配器模式是适配器模式常用的一种
代码示例
(1)5V充电器接口(目标)
//适配接口
public interface IVoltage5V {
public int output5V();
}
(2)220V充电器类(被适配的类)
public class VoItage220V {
//输出220V的电压
public int output220V(){
int src=220;
System.out.println("电压="+src+"伏");
return src;
}
}
(3)适配器类
- 实现目标接口IVoltage5V
- 创建被适配类的对象voItage220V,构造器里实例化对象
- 适配的方法output5V,在这个方法里先取到220V的信息,然后进行再处理,适配成5V
类适配器里是用【extends VoItage220V implements IVoltage5V】,然后重写IVoltage5V的方法,调用VoItage220V的方法
对象适配器是用【implements IVoltage5V】和【VoItage220V voItage220V】,重写IVoltage5V的方法,用对象voItage220V调用VoItage220V的方法
public class VoltageAdapter implements IVoltage5V {
private VoItage220V voItage220V;
public VoltageAdapter(VoItage220V voItage220V) {
this.voItage220V = voItage220V;
}
@Override
public int output5V() {
int dst=0;
if(null!=voItage220V){
int src=voItage220V.output220V();
System.out.println("使用对象适配器,进行适配");
dst=src/44;
System.out.println("适配完成,输出的电压为="+dst+"伏");
}
return dst;
}
}
(4)手机类
public class Phone {
public void charging(IVoltage5V iVoltage5V){
if(iVoltage5V.output5V()==5){
System.out.println("电压为5V,可以充电");
}else if(iVoltage5V.output5V()>5){
System.out.println("电压大于5V,不能充电");
}
}
}
(5)测试类
public class Client {
public static void main(String[] args) {
System.out.println("===对象适配器模式===");
Phone phone=new Phone();
phone.charging(new VoltageAdapter(new VoItage220V()));
}
}
UML图
对象适配器模式注意事项和细节
- 对象适配器和类适配器其实算是同一种思想,只不过实现方式不同。(用不同的方法分别取得5V和220V里的方法)
- 对象适配器根据合成复用规则,使用组合替代继承,解决了类适配器必须继承src的局限性,也不再要求dsc必须是接口
- 使用成本更低,更加灵活
接口适配器模式
基本介绍
- 当不需要全部实现接口提供的方法时,可以先设计一个抽象类实现接口,并且为该接口中每个方法提供一个默认实现(空方法),那么这个抽象类的子类可有选择地覆盖父类的某些方法来实现需求
- 适用于一个接口不想使用其所有方法的情况
代码示例
(1)接口
public interface Interface4 {
public void m1();
public void m2();
public void m3();
public void m4();
}
(2)适配器类
public abstract class AbsAdapter implements Interface4 {
@Override
public void m1() {
}
@Override
public void m2() {
}
@Override
public void m3() {
}
@Override
public void m4() {
}
}
(3)测试类
public class Client {
public static void main(String[] args) {
AbsAdapter absAdapter=new AbsAdapter() {
@Override
public void m1() {
System.out.println("使用了m1的方法");
}
};
absAdapter.m1();
}
}
适配器模式在SpringMVC框架应用的源码分析
- SpringMVC中的HeadlerAdapter就是用了适配器模式