The Adapter Pattern converts the interface of a class into another interface the clients expect. Adapter lets classes work together that couldn’t otherwise because of incompatible interfaces. 适配器模式将一种接口类型转化为另一种,他用来解决类中的类型适配问题
引子 举例一个现实生活中的案例:插头转换器。比如我们的手机是两脚插头,但是家里只有三脚插座,那怎么整?答案是找一个插口转化器,把两脚的转成三脚的即可。adapter 模式的工作方式和这种解决方案完全一致。
1 2 3 4 5 6 7 +--------------------+ +-------+ +-------------+ | Your existing | |Adaptor| | Vendor | | system | | | | Class | | |---> | |---->| | | | | | | | | | | | | | +--------------------+ +-------+ +-------------+
好了现在让我们用第一章的鸭子来举例子。话说有一天,PM 突然找到小码农说,我们的客户有一个特殊要求,想要一种有着火鸡内在的鸭子。小码农满脸的黑人问号,这也行?但是 PM 不管,说下周就要产品掩饰了,你自己看着办。
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 public interface Duck { void quack () ; void fly () ; } public interface Turkey { void gobble () ; void fly () ; } public class WildTurkey implements Turkey { @Override public void gobble () { System.out.println("Gobble..." ); } @Override public void fly () { System.out.println("Fly a short distance..." ); } } public class DuckAdaptor implements Duck { private Turkey turkey; public DuckAdaptor (Turkey turkey) { this .turkey = turkey; } @Override public void quack () { turkey.gobble(); } @Override public void fly () { turkey.fly(); turkey.fly(); turkey.fly(); } } public class Client { public static void main (String[] args) { DuckAdaptor adaptor = new DuckAdaptor(new WildTurkey()); adaptor.quack(); adaptor.fly(); } }
UML 1 2 3 4 5 6 7 8 9 10 11 12 13 14 +-----------------+ +---------------+ | |---> |<<Interface>> | | Client | | Target | | | +---------------+ +-----------------+ ^ | | | +-------------+ +-----------------+ | Adapter | | Adaptee | |-------------| ---->|-----------------| | request() | | specialRequest()| | | | | +-------------+ +-----------------+
这里展示的是类 adaptor, 还有一种 class adaptor,但是由于 Java 是单继承的,语法上就不能实现 class adaptor 的这种定义。不过支持多继承的语言是可以实现的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 +-----------------+ +-------------+ +-----------------+ | |---> | Target | | Adaptee | | Client | |-------------| |-----------------| | | | request() | | specialRequest()| +-----------------+ | | | | +-------------+ +-----------------+ ^ ^ | | | | | | +-------------+ | Adapter | |-------------| | request() | | | +-------------+
项目中可能用到 Adapter 的地方 比如老代码中,很多地方会用到 Enumeration 类,但是在 JDK 1.2 时就推出了 Iterator 接口代替他。如果新的代码都时采用的 Iterator 做迭代,那么怎么兼容老的 Enumeration 呢。
可以新建一个 adapter 类,实现 iterator 接口,持有 enumeration 实现。在 client 中通过这个 adaptor 访问 enumeration。
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 public class AdapterToEnum { public static void main (String[] args) { Vector<String> strings = new Vector<>(); strings.add("a" ); strings.add("b" ); strings.add("c" ); strings.add("d" ); Enumeration<String> enumeration = strings.elements(); IteratorAdapter adapter = new IteratorAdapter(enumeration); while (adapter.hasNext()) { System.out.println(adapter.next()); } } } class IteratorAdapter implements Iterator <String > { private final Enumeration<String> enumeration; public IteratorAdapter (Enumeration<String> enumeration) { this .enumeration = enumeration; } @Override public boolean hasNext () { return enumeration.hasMoreElements(); } @Override public String next () { return enumeration.nextElement(); } }