将一个接口转换成客户希望的另一个接口,使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)。适配器模式既可以作为类结构型模式,也可以作为对象结构型模式
适配器模式
使用场景
- 系统需要使用一些现有的类,而这些类的接口(如方法名)不符合系统的需要,甚至没有这些类的源代码。
- 想创建一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。
优点
- 可以让任何两个没有关联的类一起运行。
- 提高了类的复用。
- 增加了类的透明度。
- 灵活性好。
缺点
- 过多的使用适配器,会让系统很凌乱,明明调用的这个接口的方法,里面的实现却是另一个方法
- java 最多继承一个类,所以至多只能适配一个适配者类,而且目标类必须是抽象类。
实现
- 再来一个好理解的例子,我们国家的民用电都是 220V,日本是 110V,而我们的手机充电一般需要 5V,这时候要充电,就需要一个电压适配器,将 220V 或者 100V 的输入电压变换为 5V 输出
电压接口
1 2 3 4 5 6 7
| public interface AC {
int outputAC(); }
|
电压实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public class AC110 implements AC {
@Override public int outputAC() { int ac = 110; return ac; } }
public class AC220 implements AC {
@Override public int outputAC() { int ac = 220; return ac; } }
|
适配器接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public interface DC5Adapter {
boolean support(AC ac);
int outputDC5V(AC ac); }
|
适配器实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| public class ChinaPowerAdapter implements DC5Adapter {
public static final int voltage = 220;
@Override public boolean support(AC ac) { return (voltage == ac.outputAC()); }
@Override public int outputDC5V(AC ac) { int adapterInput = ac.outputAC(); int adapterOutput = adapterInput / 44; System.out.println("使用ChinaPowerAdapter变压适配器,输入AC:" + adapterInput + "V" + ",输出DC:" + adapterOutput + "V"); return adapterOutput; } }
public class JapanPowerAdapter implements DC5Adapter { public static final int voltage = 110;
@Override public boolean support(AC ac) { return (voltage == ac.outputAC()); }
@Override public int outputDC5V(AC ac) { int adapterInput = ac.outputAC(); int adapterOutput = adapterInput / 22; System.out.println("使用JapanPowerAdapter变压适配器,输入AC:" + adapterInput + "V" + ",输出DC:" + adapterOutput + "V"); return adapterOutput; } }
|
手机充电器类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| public class Charger {
private List<DC5Adapter> adapters = new LinkedList<>();
public Charger() { this.adapters.add(new ChinaPowerAdapter()); this.adapters.add(new JapanPowerAdapter()); }
public int convertAC(AC ac) { DC5Adapter adapter = null; for (DC5Adapter ad : this.adapters) { if (ad.support(ac)) { adapter = ad; break; } } if (adapter == null){ throw new IllegalArgumentException("没有找到合适的变压适配器"); } return adapter.outputDC5V(ac); } }
|
测试如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| public class AdapterTest {
@Test public void testBasic1() throws Exception{ Adapter adapter = new Adapter();
adapter.request(); }
@Test public void testBasic2()throws Exception{ Adapter2 adapter = new Adapter2();
adapter.request();
}
@Test public void testCharger() throws Exception{
AC chinaAC = new AC220(); Charger charger = new Charger(); System.out.println("220V电压 充电 转换后的电压为:"+charger.convertAC(chinaAC));
AC japanAC = new AC110(); System.out.println("110V电压 充电 转换后的电压为:"+charger.convertAC(japanAC)); } }
|
个人理解
想复用现有接口或者方法签名,但是需要增加额外功能时使用适配器模式