适配器模式 模式引入 问题描述 想象我们要出国旅游,到了异国他乡不懂当地语言怎么办?路上卯足马力突击学习?当然可以!不过更简单的做法是,打开手机翻译软件,切换到「当地语言-中文」就可以借助它与当地人进行对话了。这样,只要我们手机里有其他语言与中文的互译,就可以走遍地球任意一个角落并和当地人沟通了,而且我们自己并不需要真正掌握任何一门外语。 当然,有时候用翻译软件有点麻烦,有不准确的情况。此时,可以在当地找一个翻译,比如领导人出访国外时会带一个翻译,刚去 NBA 打球的姚明也随时有一个翻译在身边。 模式定义 这就是适配器模式,它一般在有满足需求功能的类,但接口不符合要求,或者希望创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类协同工作时出现。
想象我们要出国旅游,到了异国他乡不懂当地语言怎么办?路上卯足马力突击学习?当然可以!不过更简单的做法是,打开手机翻译软件,切换到「当地语言-中文」就可以借助它与当地人进行对话了。这样,只要我们手机里有其他语言与中文的互译,就可以走遍地球任意一个角落并和当地人沟通了,而且我们自己并不需要真正掌握任何一门外语。
当然,有时候用翻译软件有点麻烦,有不准确的情况。此时,可以在当地找一个翻译,比如领导人出访国外时会带一个翻译,刚去 NBA 打球的姚明也随时有一个翻译在身边。
这就是适配器模式,它一般在有满足需求功能的类,但接口不符合要求,或者希望创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类协同工作时出现。总的来说,它的主要目的是希望能复用已有的类,但接口又与复用环境要求不一致。
适配器模式是将一个类的接口转换成客户希望的另外一个接口。使得原来接口不兼容的类可以一起工作。
上面的例子中,中文与其他语言的互译器以及翻译人员就是适配器,我们自己或姚明就是那个已有的满足功能的类,接口和环境就是异国他乡。
Player,以及方法 attact 和 defense。Forwards、Center 和 Guards 等,并重写抽象方法。ForeignCenter,他的方法和抽象类的不一样,需要适配。Translator 将需要适配的 ForeignCenter 转换为 Player。下面是一些注意事项:
Target 抽象类:
public abstract class Player { protected String name; public Player(String name) { this.name = name; } public abstract void attack(); public abstract void defense(); }
Target 具体类:
public class Forwards extends Player { public Forwards(String name) { super(name); } @Override public void attack() { System.out.println("前锋 " + name + " 进攻"); } @Override public void defense() { System.out.println("前锋 " + name + " 防守"); } } public class Center extends Player { public Center(String name) { super(name); } @Override public void attack() { System.out.println("中锋 " + name + " 进攻"); } @Override public void defense() { System.out.println("中锋 " + name + " 防守"); } } public class Guards extends Player { public Guards(String name) { super(name); } @Override public void attack() { System.out.println("后卫 " + name + " 进攻"); } @Override public void defense() { System.out.println("后卫 " + name + " 防守"); } }
Adaptee 类:
public class ForeignCenter { private String name; public String getName() { return this.name; } public void setName(String name) { this.name = name; } public void attack() { System.out.println("外籍中锋 " + name + " 进攻"); } public void defense() { System.out.println("外籍中锋 " + name + " 防守"); } }
Adapter 类:
public class Translator extends Player { private ForeignCenter wjzf = new ForeignCenter(); public Translator(String name) { super(name); wjzf.setName(name); } @Override public void attack() { wjzf.attack(); } @Override public void defense() { wjzf.defense(); } }
Main 方法:
public class Main { public static void main(String[] args) { Player b = new Forwards("巴蒂尔"); b.attack(); Player m = new Guards("麦克格雷迪"); m.attack(); Player ym = new Translator("姚明"); ym.attack(); ym.defense(); } }
执行结果:
前锋 巴蒂尔 进攻 后卫 麦克格雷迪 进攻 外籍中锋 姚明 进攻 外籍中锋 姚明 防守

实际中的例子:复用功能但接口不符,俗称包一层。
适配模式优点包括:
适配模式缺点包括: