适配器是将两个不兼容的类融合在一起,它有点像粘合剂,将不同的东西通过一种转换使得它们能够协作起来。例如,经常碰到要在两个没有关系的类型之间进行交互,第一个解决方案是修改各自类的接口,但是如果没有源代码或者我们不愿意为了一个应用而修改各自的接口,此时怎么办?这种情况我们往往会使用一个 Adapter ,在这两种接口之间创建一个 “混血儿” 接口,这个 Adapter 会将这两个接口进行兼容,在不修改原有代码的情况下满足需求。
1 适配器模式 UML
冲突:Target 期待调用 operation2 方法,而 Adaptee 并没有(这就是所谓的不兼容了)。
解决方案:为使 Target 能够使用 Adaptee 类里的 operation3 方法,故提供一个中间环节Adapter类(继承 Adaptee & 实现 Target 接口),把Adaptee 的 API 与 Target 的 API 衔接起来(适配)。
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 public interface Target { void operation2 () ; } public class Adaptee { public void operation3 () { System.out.println("被适配者的方法" ); } } public class Adapter extends Adaptee implements Target { @Override public void operation2 () { super .operation3(); } } Target adapterTarget = new Adapter(); adapterTarget.operation2();
这是继承的方式,当然也可以用组合的方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class Adapter implements Target { Adaptee adaptee; public Adapter (Adaptee adaptee) { this .adaptee = adaptee; } @Override public void operation2 () { adaptee.operation3(); } } Target adapterTarget = new Adapter(new Adaptee()); adapterTarget.operation2();
2 装饰模式案例 电压适配器 我们国家的民用电都是 220V,有些国家是 110V,而我们的手机充电一般需要 5V,这时候要充电,就需要一个电压适配器,将 220V 或者 100V 的输入电压变换为 5V 输出。
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 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 public interface AC { int outputAC () ; } public class AC110 implements AC { public final int output = 110 ; @Override public int outputAC () { return output; } } public class AC220 implements AC { public final int output = 220 ; @Override public int outputAC () { return output; } } public interface DC5Adapter { boolean support (AC ac) ; int outputDC5V (AC ac) ; } public class PowerAdapter110 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("使用 PowerAdapter110 变压适配器,输入AC:" + adapterInput + "V" + ",输出DC:" + adapterOutput + "V" ); return adapterOutput; } } public class PowerAdapter220 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("使用 PowerAdapter220 变压适配器,输入AC:" + adapterInput + "V" + ",输出DC:" + adapterOutput + "V" ); return adapterOutput; } } public class Client { private List<DC5Adapter> adapters = new LinkedList<>(); public Client () { this .adapters.add(new PowerAdapter220()); this .adapters.add(new PowerAdapter110()); } public DC5Adapter getPowerAdapter (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; } public void Adapter () { Client test = new Client(); AC ac = new AC110(); DC5Adapter adapter = test.getPowerAdapter(ac); adapter.outputDC5V(ac); } }
4 Android 源码中的适配器模式 说起 Android 最常见的就是 Adapter 了吧,那就整个学习一下 RecyclerView 、LayoutManager 和 Adapter
通过桥接模式 ,使 RecyclerView 将布局方式独立成 LayoutManager,实现对布局的定制化。
通过组合模式 ,使 RecycleView 通过 dispatchLayout 对 Item View 进行布局绘制的。
通过适配器模式 ,ViewHolder 将 RecycleView 与 ItemView 联系起来,使得 RecycleView 方便操作 ItemView。
通过观察者模式 ,给 ViewHolder 注册观察者,当调用 notifyDataSetChanged 时,就能重新绘制。
RecyclerView 源码解析
RecyclerView 相关面试
感谢
设计模式之美
《Android 源码设计模式解析与实战》
以及上文中的链接