设计模式之适配器模式

工作原理:

  1. 将一个类的接口转换成客户希望的另外一个接口,Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作
  2. 从用户的角度看是看不到被适配者的,是解耦的

适配器模式属于结构型模式,主要分三类:类适配器模式、对象适配器模式、接口适配器模式

类适配器模式

假设我们现在有这么一个需求:需要给我们的手机充电,手机充电只能使用5V的电压,但是我们家里的插座却是220V的电压,也就是说手机无法直接使用220V的插座进行充电,那么现在就需要一个适配器来进行5V电压和220V电压的转换,这个适配器就是我们平时所用的充电器。

类图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rTgsoVAJ-1593147607998)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200414024316248.png)]

代码实现:

//被适配的类
public class Voltage220V {
	//输出 220V 的电压
	public int output220V() {
		int src = 220;
		System.out.println("电压=" + src + "伏");
		return src;
    }
}
//适配接口
public interface IVoltage5V {
	public int output5V();
}
//适配器类
public class VoltageAdapter extends Voltage220V implements IVoltage5V {
	@Override
	public int output5V() {
		//获取到 220V 电压
		int srcV = output220V();
		int dstV = srcV / 44 ; //转成 5v
		return dstV;
	}
}
//手机类
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, 不能充电~~");
		}
	}
}
//客户端
public class Client {
	public static void main(String[] args) {
		System.out.println(" === 类适配器模式 ====");
		Phone phone = new Phone();
		phone.charging(new VoltageAdapter());
	}
}

通过上面的例子,我们再来理解一下适配器模式的工作原理,就非常清晰了;适配器模式的工作原理是说将一个类的接口转换成客户希望的另外一个接口,代入上面的例子中,也就是说把已存在的220V这个类转换成手机充电需要的5V接口了;另外,Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作;即指的是由于手机不能直接与220V的电压一起工作,但是有了适配器之后,就使得手机可以与220V电压一起工作了(间接)

关于类适配器:

  • Java 类是单继承机制,有一定局限性;因为类适配器需要继承被适配器类, 这就要求目标必须是接口了。
  • 被适配器类的方法在 Adapter 中都会暴露出来,也增加了使用的成本。
  • 由于适配器继承了被适配器类,所以它可以根据需求重写被适配器类的方法,使得适配器的灵活性增强了。

对象适配器

类图如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bhWiwSvl-1593147608001)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200414140201742.png)]

代码如下:
只提供适配器类的代码,其它代码可以参考类适配器模式

//适配器类
public class VoltageAdapter implements IVoltage5V {
    //使用聚合
    private Voltage220V voltage220V;
    public VoltageAdapter(Voltage220V voltage220V){
        this.voltage220V=voltage220V;
    }
    
    @Override
	public int output5V() { 
		int dst = 0;
		if(null != voltage220V) {
			int src = voltage220V.output220V();//获取 220V 电压
			System.out.println("使用对象适配器,进行适配~~");
			dst = src / 44;
			System.out.println("适配完成,输出的电压为=" + dst);
		}
		return dst;
    }
}

关于对象适配器:

  • 对象适配器和类适配器其实算是同一种思想,只不过实现方式不同。根据合成复用原则,使用组合替代继承, 所以它解决了类适配器必须继承被适配器类的局限性问题,也不再要求目标必须是接口。
  • 使用成本更低,更灵活。

接口适配器模式

核心思路:当不需要全部实现接口提供的方法时,可先设计一个抽象类实现接口,并为该接口中每个方法提供一个默认实现(空方法),那么该抽象类的子类可有选择地覆盖父类的某些方法来实现需求;适用于一个接口不想使用其所有的方法的情况。

为什么要使用适配器接口呢?试想,如果我们的目标接口中有多个方法需要进行适配,那么每一个适配器去实现这个目标接口的话都需要实现接口中的所有方法,但是这个适配器类只需要针对某一个方法进行适配,而每次都要实现所有方法,即使是空实现,也会使代码变得非常冗余,所以才需要适配器接口;让这个适配器接口去实现目标接口所有方法(空实现),而具体的适配器再去继承适配器接口,再针对需要的方法去重写即可!

类图如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gtzBDsab-1593147608006)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200414160712878.png)]

代码如下:

//被适配的类
public class Voltage220V {
	//输出 220V 的电压
	public int output220V() {
		int src = 220;
		System.out.println("电压=" + src + "伏");
		return src;
  }
}
//目标接口:可能是5V、9V、12V、24V
public interface IVoltage {
	int output5V();
	int output9V();
	int output12V();
	int output24V();
}
//适配器抽象类,也可以直接说成是适配器接口,是一个万能适配器,可以实现多种电压的转换
//适配器接口是一个抽象类,实现了目标接口,并重写了目标接口的所有方法,只是这些方法都是空实现
//只需要让具体的适配器去继承这个适配器接口,并对需要的方法进行重写即可!
public abstract class abstractAdapter implements IVoltage{
	
	@Override
	public int output5V() {
		return 0;
	}

	@Override
	public int output9V() {
		return 0;
	}

	@Override
	public int output12V() {
		return 0;
	}

	@Override
	public int output24V() {
		return 0;
	}
	
}
//具体的适配器类:实现5V-220V的转换
public class Adapter extends abstractAdapter {

    private Voltage220V voltage220V;
	
	public Adapter(Voltage220V voltage220V) {
		this.voltage220V=voltage220V;
	}
	
	@Override
	public int output5V() {
		int src = voltage220V.output220V();
		int des=src/44;
		return des;
	}	
}
//手机类
public class Phone {
	//充电
	public void charging(IVoltage iVoltage) {
		if(iVoltage.output5V() == 5) {
			System.out.println("电压为 5V, 可以充电~~");
		} else if (iVoltage.output5V() > 5) {
			System.out.println("电压大于 5V, 不能充电~~");
		}
	}
}
//客户端
public class Client {
	public static void main(String[] args) {
		System.out.println(" === 类适配器模式 ====");
		Phone phone = new Phone();
		phone.charging(new Adapter(new Voltage220V()));
	}
}

关于适配器模式在SpringMVC中的应用可以参考另一篇博客:https://blog.csdn.net/can_chen/article/details/105524137

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值