定义:适配器模式(Adapter),是将一个类的接口转换成客户希望的另外一个接口,从而使得原本由于接口不兼容而不能一起工作的哪些类可以一起工作。在软件开发中,也就是系统的数据和行为都正确,但接口不符时,我们应该考虑用适配器,目的是使控制范围之外的一个原有对象与某个接口匹配。适配器模式主要用于希望复用一些现有的类,但接口又与复用环境要求不一致的情况。
类图:
角色及其职责
Target:客户所期待的接口。目标可以是具体的或抽象的类,也可以是接口。
Adaptee:需要适配的类。
Adapter:通过内部封装一个Adapter对象,把源接口转换成目标接口。
代码示例:
目标类:Player
package com.jin.model.adapter;
/**
*
* @author michael
* Target:目标类,可以是接口,抽象类或者具体的类
*
*/
public abstract class Player {
protected String name;
public Player(String name) {
this.name = name;
}
public abstract void attack();
public abstract void defense();
}
具体类:前锋Forwards
package com.jin.model.adapter;
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 + "开始防守");
}
}
具体类:中锋Center
package com.jin.model.adapter;
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 + "开始防守");
}
}
具体类:后卫Guard
package com.jin.model.adapter;
public class Guard extends Player {
public Guard(String name) {
super(name);
}
@Override
public void attack() {
System.out.println(name + "开始进攻");
}
@Override
public void defense() {
System.out.println(name + "开始防守");
}
}
需要适配的类:ForeignCenter(不会说英文)
package com.jin.model.adapter;
/**
*
* @author michael
* 适配器模式中Adaptee,即需要改造的类
*
*/
public class ForeignCenter {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void attack() {
System.out.println("外籍中锋" + name + "开始进攻");
}
public void defense() {
System.out.println("外籍中锋" + name + "开始防守");
}
}
适配类:Translator(翻译)
package com.jin.model.adapter;
/**
*
* @author michael
* 适配器模式中Adapter
*
*/
public class Translator extends Player {
private ForeignCenter center = new ForeignCenter();
public Translator(String name) {
super(name);
center.setName(name);
}
@Override
public void attack() {
center.attack();
}
@Override
public void defense() {
center.defense();
}
}
客户端:测试
package com.jin.model.adapter;
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
Player bd = new Forwards("巴蒂尔");
bd.attack();
Player mk = new Guard("麦克格雷迪");
mk.defense();
Player ym = new Translator("姚明");
ym.attack();
}
}
Adapter在.NET中的应用:
在ADO.NET中,对于我们从数据库中取出的数据都要放到一个DataSet中,不管你是Access的数据库,还是SQL的数据库,或者是Oracle的数据库都要放到DataSet中。.NET中并没有提供如:SqlDataSet、OleDbDataSet、OracleDataSet等,它只提供了一种DataSet就是用SqlDataAdapte等去填充数据;为什么这一个DataSet能存放不同的数据呢?就是有这些适配器来适配。
DataAdapter结构图:
要点:
1.Adapter模式主要应用于“希望复用一些现存的类,但是接口又与复用环境要求不一致的情况”,在遗留代码复用、类库迁移等方面非常有用。
2.Adapter模式有对象适配器和类适配器两种形式的实现结构,但是类适配器采用“多继承”的实现方式,带来了不良的高耦合,所以一般不推荐使用。对象适配器采用“对象组合”的方式,更符合松耦合精神。
适用性:
1.系统需要使用现有的类,而此类的接口不符合系统的需要。
2.想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。这些源类不一定有很复杂的接口。
3.(对对象适配器而言)在设计里,需要改变多个已有子类的接口,如果使用类的适配器模式,就要针对每一个子类做一个适配器,而这不太实际。