定义
适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。
类适配器模式
使用继承的方式实现没有提供的接口从而达到适配到新系统的需求。
对象适配器模式
使用聚合的方式提供新系统需要的所有接口。
UML
优点
- 更好的复用性:系统需要使用现有的类,而此类的接口不符合系统的需要。那么通过适配器模式就可以让这些功能得到更好的复用。
- 更好的扩展性:在实现适配器功能的时候,可以调用自己开发的功能,从而自然地扩展系统的功能。
- 将目标类和适配者类解耦。
- 增加了类的透明性和复用性,将具体的实现封装在适配者类中,对于客户端类来说是透明的,而且提高了适配者的复用性。
- 灵活性和扩展性都非常好,符合开闭原则。
缺点
- 过多的使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是A接口,其实内部被适配成了B接口的实现,一个系统如果太多出现这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。
应用场景
- 想使用一个已经存在的类,但如果它的接口和你的要求不相同时。可以使用适配器模式。两个类所做的事情相同或相似,但接口不同时可以使用。
经典例子
里皮翻译用汉语布置恒大队员战术。球员都继承于中国人,都会说汉语,而里皮并不会说汉语。在不知战术的时候,我们需要给里皮一个翻译,这个翻译就是里皮的适配器。翻译可以和球员一样,也继承于中国人,也有说汉语这个方法。而翻译认识里皮,翻译在说汉语()这个方法的时候,实际上是在说里面用意大利语的内容。
示例
使用适配器模式适配新的员工信息。
Java
1 public class Main 2 { 3 public static void main(String[] args) 4 { 5 //类适配器模式使用 6 IMSEmployeeInfo info = new MSEmployeeInfo1(); 7 System.out.println(info.nickname()); 8 9 //对象适配器模式使用 10 IEmployeeInfo info2 = new EmployeeInfo(); 11 IMSEmployeeInfo info3 = new MSEmployeeInfo2(info2); 12 System.out.println(info3.nickname()); 13 } 14 15 /** 16 * 员工信息接口 17 */ 18 public static interface IEmployeeInfo 19 { 20 /** 21 * 工号 22 */ 23 int id(); 24 25 /** 26 * 姓名 27 */ 28 String name(); 29 } 30 31 /** 32 * 员工信息类 33 */ 34 public static class EmployeeInfo implements IEmployeeInfo 35 { 36 @Override 37 public int id() { 38 return 250; 39 } 40 41 @Override 42 public String name() { 43 return "李二狗"; 44 } 45 } 46 47 /** 48 * 需要接入的MS公司员工信息接口 49 */ 50 public static interface IMSEmployeeInfo 51 { 52 /** 53 * 工号 54 */ 55 int id(); 56 57 /** 58 * MS公司不使用人物的真名, 而是给员工取了一个英文名 59 */ 60 String nickname(); 61 } 62 63 /** 64 * 类适配器模式的实现 65 */ 66 public static class MSEmployeeInfo1 extends EmployeeInfo implements IMSEmployeeInfo 67 { 68 @Override 69 public String nickname() { 70 //这里通过查询得到了李二狗的英文名并返回 71 return "尼古拉斯"; 72 } 73 } 74 75 /** 76 * 对象适配器模式的实现 77 */ 78 public static class MSEmployeeInfo2 implements IMSEmployeeInfo 79 { 80 private IEmployeeInfo _info; 81 82 public MSEmployeeInfo2(IEmployeeInfo info) 83 { 84 _info = info; 85 } 86 87 @Override 88 public int id() { 89 return _info.id(); 90 } 91 92 @Override 93 public String nickname() { 94 //这里通过查询得到了李二狗的英文名并返回 95 return "尼古拉斯"; 96 } 97 } 98 }